Pythonでは簡潔に記述できる事でも、C++98では膨大なテンプレコードを書く必要があります。参考に(?)C++とPythonのコードを並べてみました。
一言でいうと「シンタックスシュガーと動的型付けってすばらしい」
(書きかけなので、今後項目が増えるかもしれません)
その1 静的型付け/動的型付け
Point get_distance(const Point& point1, const Point& point2) {
return sqrt( pow(point1.x - point2.x, 2) + pow(point1.y - point2.y, 2);
}
def get_distance(point1, point2):
pt1_x, pt1_y = point1
pt2_x, pt2_y = point2
return math.sqrt((pt1_x - pt2_x) ** 2, (pt1_y - pt2_y) ** 2)
C++:型に加えconst、*やら&、テンプレートといった修飾子などが煩わしい。(入出力が明示かされたり、コンパイル時の構文チェックは助かるけども・・・)
Python:動的型付けなので、型定義が不要。型は変数ではなく値が持つ.
その2 リストとディクショナリ
vector<double> calculate(const vector<Line>& lines) {
vector<double> result;
vector<Line>::const_iterator ite = lines.begin();
while( ite != lines.end() ) {
double value = 何かする(*ite);
result.push_back(value);
++ite;
}
return result;
}
def calculate(lines):
result = [] // []でリスト形式, {}だとディクショナリ.
for line in lines:
value = 何かする(line)
result.append(value)
return result
C++: C++98では、シンタックスシュガーなし(C++11はシンタックスシュガー有り)。
python: オブジェクトの生成、要素へのアクセス、ループにシンタックスシュガー有り。上のケースはリスト内包表記を使うとさらに簡潔に記述できる。
def calculate(lines):
result = [ 何かする(line) for line in lines]
return result
その3 タプル
void foo() {
Point pt1(0,1);
Point pt2(0,5);
Line line(pt1, pt2);
double score;
double distance;
calculate(line, &score, &distance);
...
}
void calculate(const Line& line, double* out_score, double* out_distance) {
*out_distance = get_distance(line.point1, line.point2);
*out_score = get_score(line);
}
double get_distance(const Point& pt1, const Point& pt2) {...}
def foo():
pt1 = (0,1)
pt2 = (0,5)
line = (pt1, pt2)
distance, score = caclculate(line)
...
def calculate(line):
distance = get_distance(*line)
score = get_score(line)
return distance, score
def get_distance(pt1, pt2):
...
C++:値をまとめたいときは、汎用のpairを使うか、PointやLineのように構造体/クラスを定義する必要がある。これも構文チェックとのトレードオフ。
Python:タプルを使えば、ちょっとしたペアを引数に渡したいときに重宝します。使いすぎると、可読性が下がる。
その4 ラムダ式
void foo(const Line& line, double x) {
double y1 = func(line, x);
double y2 = func(line, x+1);
}
// 直線line上のxに対応するy座標を求める.
// ※:y=1やx=0といった線は考慮しない.
double func(const Line& line, double x) {
// 傾き取得
double slope = get_slope(line.point1, line.point2);
double const_value = get_const_value(line.point1, slope);
double y = x * slope + c;
return y;
}
def foo(line, x):
func = get_func(line)
y1 = func(x)
y2 = func(x + 1)
def get_func(line):
slope = get_slope(*line)
const_value = get_const_value(line[0], slope)
return (lamda x: x * slope + c)
pythonではラムダ式が提供されているので、ちょっとした事が簡単に記述できるようになります。
C++ならクラスを書けば、再利用性は上がるけど書くための敷居が高い。
その5 関数呼び出し
タプルやリストを自動的に個別の引数に展開してくれたり、名前付き引数できたりと楽ができます。
例: C++の関数のオーバーロードを減らす。
doule get_distance(const Point& pt1, const Point pt2) {
return //演算結果
}
double get_distance(const Line& line) {
return get_distance(line.point1, line.point2);
}
def get_distance(point1, point2):
return ...
def foo(line):
get_distance(*line) // lineがタプルかシーケンスなら、自動的にpoint1, point2に展開してくれる.