Pythonを学びたいけど、Javaしか知らないプログラマが取るべき次なる行動とは
最近、Pythonというキーワードをよく耳にします。
ところが多くのプログラマ、特にSES事業で仕事をしている方々は、今も昔もそしてこれからもJavaを使うことが多いでしょう。
でも、これだけPythonがはやり始めると、Pythonがちょっと気になりますよね。Pythonってどんな言語なのでしょうか?
そこで本記事は、Javaプログラマの皆さまに向けてPythonを雑学風に解説します。
本記事を通じて、Pythonは決して難解でトリッキーな言語ではなく、いたって普通の言語であることを知っていただければ幸いです。
目次
Javaから見たPythonとは
Pythonってどんな言語?というと、機械学習やAI、ビッグデータ解析といったトレンドキーワードが浮かびます。
でも、プログラマとしてはそんなことよりも「コード」が見たいですよね。そう、我々プログラマはコードで語る生き物なのです・・・
JavaにあるものはPythonにもあるのか、という視点をもとに話を進めます。もう一歩踏み込んで、Javaを知っているのなら、Pythonを知るのも十分可能であるとお気づきいただければ幸いです。
Pythonの制御構文
まずは1から10までの合計を計算してみましょう。
Java
public class Main {
public static void main(String[] args) throws Exception {
int sum = 0;
for(int cnt = 0 ; cnt <= 10 ; cnt++) {
sum = sum + cnt;
}
System.out.println("合計:" + Integer.toString(sum));
}
}
Python
sum = 0
for i in range(1, 11):
sum = sum + i
print('合計:' + str(sum))
もう早速ちがいが見えてきましたね。順に見ていきましょう。
Pythonのコードには、波カッコ { } がありません。Javaプログラマにとっては一番違和感を感じるところです。そうです、Pythonはインデントの数でブロックを表すのです。
でも、よく考えると合理的です。プログラムってインデントを合わせるのが一般的かつマナーです。であれば、波カッコを書かないほうが行数は少なくて済みます。
Javaのプログラムはfor文でループさせているのに対し、Pythonはrange関数で1〜10までの値をもつリスト(後述)を生成させて、リストの要素を変数iに順次代入しています。
Javaでも拡張for文を使って似たようなことができますが、メソッドに頼らず自前で配列やリストを作る必要があります。
ちょっと工夫を加えて、偶数だけを足すように制御文を入れてみましょう。
Java
public class Main {
public static void main(String[] args) throws Exception {
int sum = 0;
for(int cnt = 0 ; cnt <= 10 ; cnt++) {
if(cnt % 2 == 0) {
sum = sum + cnt;
}
}
System.out.println("合計:" + Integer.toString(sum));
}
}
Python
sum = 0
for i in range(1, 11):
if i % 2 == 0:
sum = sum + i
print('合計:' + str(sum))
if文もやはりインデントでブロックを表します。
それ以前に、このように並べてみると、やはり行数のちがいは明確です。Pythonはシンプル、という世間の評判はホントのようです。
Pythonの制御構文、ちょっとまとめてみましょう。
for 変数 in データの集まり:
処理
処理
if 条件式1:
条件式1がtrueの時の処理
elif 条件式2:
条件式2がtrueの時の処理
・
・
・
else:
全て当てはまらない時の処理
ご覧になってお分かりのとおり、Javaプログラマならピンとくる構文ばかりです。
変数
変数の概念そのものはJavaと同じです。型もほとんどJavaと変わりません。よって、型の細かな差を語るより超重要なことがあります。
それは宣言時に型を決める必要はないということです。「int a = 1」と書く必要はなく「a = 1」とすればaは整数型となります。
また、JavaにはないPythonらしい代入方法をお見せします。
b, c = 10, 20
d = e = 30
JavaならIDEが即座に真っ赤に着色しそうな構文ですね。Pythonなら可能です。しかも慣れるとJavaよりシンプルに書けそうです。
データ構造
実務ではとても大事なテーマ「データ構造」です。Javaでは配列、リスト、マップ・・・があります。ではPythonではどうでしょうか?
最初に、配列を見てみましょう。
Javaでは非常によく見る配列、例えばこんな感じです。
int[] a = {1, 2, 3, 4, 5};
Pythonではこうなります。Pythonでは配列というものはなく、リストがそれに相当します。
a = [1, 2, 3, 4, 5]
表現がちがうだけで一緒?と思いますが微妙に異なります。
Javaでは、配列の要素は全て同じでなければなりません。もしJavaでちがう型の値やオブジェクトを格納したければ、リストを使います。
リストはPythonとJavaの両方にあるので、比べてみましょう。
Java
public class Main {
public static void main(String[] args) throws Exception {
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
for(Integer i : list) {
System.out.println(i.toString());
}
}
}
Python
list = []
list.append(1)
list.append(2)
list.append(3)
list.append(4)
for i in list:
print(i)
なんだかなあ・・・というくらい、ちがいますね。
JavaやPythonのリストには、異なる型の要素を格納できます。でも、それだと何が入るか予想できず、予期せぬ型の要素が入ればエラーになります。それを防ぐために、Javaではおなじみのジェネリクスを使います。
上記のJavaのサンプルはInteger型で限定しています。Pythonの方は指定していません。Pythonで型を限定するときは、NumPyのnpというものを使います。
ところで、Javaにおいて配列やリストと同じくらい大事なデータ構造、それはMapです。JavaのMapはこんな感じ。
Java
public class Main {
public static void main(String[] args) throws Exception {
Map<String, String> map = new HashMap<>();
map.put("a", "1");
map.put("b", "2");
System.out.println(map.get("a"));
}
}
同じものがPythonにもあります。それは辞書です。辞書って名前がヘンですね。辞書はMapと同じように、キーにひもづく値を格納します。
dict = {}
dict['a'] = '1'
dict['b'] = '2'
print(dict['a'])
その他、複数の要素を格納するのにタプルというデータ構造があります。リストと同じようなものですが、こちらは一度宣言すると変更できません。
tuple = (1,2,3,4,5)
print(tuple[1])
タプルは内容や順序を変更したくないときに使います。これはJavaにはないデータ構造ですね。
クラス・オブジェクト
クラスの定義とインスタンス化を、JavaとPythonでそれぞれ記述してみましょう。お題は、生徒(student)クラスです。クラスには出席番号(no)と氏名(name)というフィールドがあり、それぞれをカプセル化してアクセサメソッドを定義してみましょう。
Java
public class Student {
private int no;
private String name;
public Student(int no, String name) {
this.no = no;
this.name = name;
}
public int getNo() {
return this.no;
}
public void setNo(int no) {
this.no = no;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
}
public class Main {
public static void main(String[] args) throws Exception {
Student student = new Student(1,"生徒1");
System.out.println(Integer.toString(student.getNo()));
System.out.println(student.getName());
}
}
Python
class Student:
def __init__(self, no, name):
self.__no = no
self.__name = name
def getno(self):
return self.__no
def setno(self, no):
self.__no = no
def getname(self):
return self.__name
def setname(self, name):
self.__name = name
student1 = Student(1, '生徒1')
print(student1.getno())
print(student1.getname())
順に解説していきましょう。
Pythonにおいて、__init__はコンストラクタです。変数名の前に__を付ければスコープがプライベートになるのでカプセル化ができます。よって、アクセサを作りました。
インスタンス化するときは、変数名=クラスでOKです。newキーワードはありませんがイメージ的には分かりますね。
あとはインスタンスに対してドット演算子でメソッドを呼び出すだけです。
表現はかなりちがうものの、プログラミング言語として一般的なものはだいたい両方に存在していることにお気づきでしょうか?
科学技術計算はPython!といわれる理由(NumPy)
Pythonは科学技術計算が得意、という意見を聞いたことがあるでしょう。ほんの入り口だけですがご紹介しましょう。
Pythonは、科学技術計算用のライブラリ「NumPy」が使えます。import文で組み込みだけですぐに使えます。
試しに、リストの要素の平均をNumPyで出してみましょう。
import numpy as np
a = np.array([12, 23, 34, 45, 56])
print(np.average(a))
これを実行しても34.0という結果が返ってくるだけで、ありがたみを感じません。
では、行列の逆行列を求めるといった複雑な計算はどうでしょうか?Javaなら多次元配列を用意して・・・とかなり複雑になります。
では、PythonでNumPyを使うとどうなるか、2×2の行列([1,2],[3,4])で試しましょう。
import numpy as np
sample = np.array([[1,2],[3,4]])
print(np.linalg.det(sample))
print(np.linalg.inv(sample))
結果は次のようになります。
-2.0
[[-2. 1. ]
[ 1.5 -0.5]]
行列式はnp.linalg.det()で-2.0、逆行列はnp.linalg.inv()によって
[[-2. 1. ]
[ 1.5 -0.5]]
という結果が求められます。
こんな感じで、NumPyを使えば、複雑な科学技術計算がいとも簡単に実装できるのです。言い方を変えれば、NumPyをimportするだけで、すざまじい数の科学計算(例えば数学的な計算や統計計算など)が実装できるのです。
Pythonは科学計算が得意といわれる理由がここにあります。
Python周辺知識
Pythonってホントにシステム開発に使えるのかな?実務的にどうかな?と思ってしまいますよね。ここでは、PythonのテストツールやWebフレームワークについて解説します。
Pythonのテストツール
JavaではテストツールとしてJUnitを使います。Junitは一般的に広く普及しているツールなので、使ったことがある方も多いでしょう。
JavaでJUnitがあるように、Pythonにも「unittest」というテストツールがあります。以下は、plusという足し算のメソッドをテストしている例です。
テスト対象:plus.py
def plus(a, b):
return a + b
テストコード:test_plus.py
import unittest
import plus
class TestPlus(unittest.TestCase):
def test_plus(self):
a = 1
b = 2
expected = 4
actual = plus.plus(a, b)
self.assertEqual(expected, actual)
結果は以下の通りです。
================================================================
FAIL: test_plus (test_plus.TestPlus)
----------------------------------------------------------------
Traceback (most recent call last):
File "/Users/hondaminori/pytest/test_plus.py", line 11, in test_plus
self.assertEqual(expected, actual)
AssertionError: 4 != 3
----------------------------------------------------------------
Ran 1 test in 0.000s
FAILED (failures=1)
1+2=4というテストケースに対して、実際にはplusメソッドは3を返すので、結果が合わずエラーとなりました。もちろんテストケース側のexpectedを3にすると、OKという結果が返ります。
assertEqualなんて、JUnitと似ていますね。もちろんJunitと同じく、assertEqual以外に多数のメソッドがあります。これもJunitと同じです。
Webフレームワーク
Pythonは、WebフレームワークがあるのでWebシステムも開発できます。以下はPythonのWebフレームワークです。
- Django(ジャンゴまたはディージャンゴと呼ぶ)
- Flask
- Bottle
現在のところDjangoが一番優位ですが、よりシンプルや軽量を求めるエンジニアはFlaskやBottleを採用します。
Djangoは国内ではまだマイナーな存在ですが、海外ではメジャーな存在です。いずれ日本も普及するものと思われます。
「Pythonを触ってみたい!」「興味が湧いたので、今すぐチョットだけ触ってみたい!」という方は、paiza.IOをオススメします。
このサイトは、環境構築を一切必要とせず、なんとブラウザベースでPythonのコードを実行できます!本記事でご紹介したコードは、unittestのコードを除いてすべてコピペで実行可能です。
実は本記事の執筆も、このサイトを使いました。
まとめ
Javaから見たPythonというテーマで進めてきましたが、いかがでしたか?
PythonはJavaと比較しても言語としての基本は変わらないし、テストツールやWebフレームワークもあります。
Javaプログラマの方々、データ解析やAIといった壮大な切り口ではなく、ぜひコードから試してみることをオススメします。