はじめに
普段、IT企業で働いている「プログラマー芸人・ジンバ」と申します。
初心者がまず始めるプログラミング言語でPythonを使う方が多いのではないでしょうか。書店に行っても「Python入門」といった本が多く並んでいます。
今回はそんなPythonの悪口を10個言っていきます。なんでそんなことする必要があるの、という意見あると思いますがこの記事を開いてる時点であなたも同罪です。ひとまず見ていってください。
動画で見たい方はこちら↓
①『遅い!!』
C,C++などはコンパイラ型言語です。一度にすべてのソースコードを機械語(実行ファイル)に変換します。
機械語に変換済みだから、実行する実行速度が速いです。
ところが、Pythonはインタプリタ型言語でソースコードを1行ずつ解釈して実行します。毎回解釈が必要なので実行速度が遅めです。
※コンパイルすることも可能みたいです。
②『動的型付け言語なので不安』
CやJavaなどの静的型付け言語はコンパイル時に型のミスをチェックしてくれて安全性が高いです。
// C(静的型付け)
#include <stdio.h>
int main() {
int x = 10; // 整数型として宣言
printf("%d\n", x);
// x = "hello"; // ← エラー!型が違うのでコンパイルできない
return 0;
}
一方、Pythonは動的型付け言語なので変数の型を実行時に自動的に決定します。
# Python(動的型付け)
x = 10 # 整数
print(x)
x = "hello" # 今度は文字列を代入してもOK
print(x)
動的型付け言語だと、 型ミスに気づくのは実行時なので修正が面倒です。
③『Python2とPython3で混乱を招いた』
Python2からPython3にアップデートする際、大きな変更があり混乱を招きました。
まず文法が変わりました。
# Python2(SyntaxErrorが起こる)
print "Hello, world"
# Python3
print("Hello, world")
標準ライブラリの関数名が変更されました。そのためインポートの失敗が続出しました。
# Python 2
import ConfigParser
import StringIO
# Python 3
import configparser
import io
ただメジャーアップデートはPythonに限らず、どの言語でも破壊的変更が行われるものです。(←じゃあ言うなよ)
④『インデントがダルい』
C,Javaなどはロックは 中カッコ{}で囲みます。
#include <stdio.h>
void check_number(int x) {
if (x > 0) {
printf("Positive\n");
} else {
printf("Non-positive\n");
}
}
一方、Pythonは
- ifやelseの中に入る処理はインデントでブロックを定義。
- インデントがズレていると文法エラーになる
- タブとスペースの混在もダメ
- 長いとどこからどこがfor文の中か分かりにくい
def check_number(x):
if x > 0:
print("Positive")
else:
print("Non-positive")
⑤『GUI開発が弱い』
TkinterとかKivyぐらいしか無いです。「Pythonでアプリ作るぞ!」は違うかなと。
⑥『バージョンアップ対応が面倒!』
バージョンアップによって依存していたAPIや文法が廃止されライブラリが動かなくなります。
機械学習でたくさんライブラリを入れるので管理が大変です。仮想環境やDockerで固定する必要があります。
(これもPythonに限った話ではないが)
⑦『機械学習できることに甘えている』
先述の通り、欠点が多いです。NumPyなどはC/C++で高速化されたライブラリに依存しているため、実際の 機械学習の計算はPythonでは行っていないです。
(Javaなどもそうでは?)
⑧『パッケージ管理が面倒』
ツール | 役割 |
---|---|
pip | Python パッケージのインストール(PyPI) |
conda | パッケージ & 仮想環境管理(Anaconda系) |
venv | Python 標準の仮想環境作成ツール) |
poetry | モダンな依存管理とビルド |
virtualenv | 古くからある仮想環境ツール |
混在使用すると環境が壊れ、パッケージの依存関係が破綻します。
⑨『list, tuple, setがややこしい』
参考書で初めて見た時、皆様も混乱したのではないでしょうか?
list(リスト)
- 中身を追加・削除・変更できる。
- [] で囲む。
fruits = ['apple', 'banana', 'orange']
print(fruits[0]) # 'apple'
fruits.append('grape') # 追加
print(fruits) # ['apple', 'banana', 'orange', 'grape']
fruits[1] = 'melon' # 値の変更
print(fruits) # ['apple', 'melon', 'orange', 'grape']
tuple(タプル)
- 中身の追加や変更はできない。
- ()で囲む
colors = ('red', 'green', 'blue')
print(colors[1]) # 'green'
# colors[1] = 'yellow' # ← エラー!タプルは変更不可
set(集合)
- 中身を追加・削除・変更できる。
- 重複を許さない、順序なし
- {}で囲む
fruits = {'apple', 'banana', 'apple', 'orange'}
print(fruits) # {'apple', 'banana', 'orange'} ← 重複が消える
fruits.add('grape') # 要素の追加
print(fruits)
# 存在チェックが高速
print('apple' in fruits) # True
⑩『Pythonicって結局なに?』
Pythonicとは「Pythonらしい書き方・考え方」のことらしいです。冗長なコードよりも、簡潔で明確なコードを目指せ、と。別に誰が決めたとかでは無いみたいです。なんだそりゃ。
普通のコード
result = []
for n in numbers:
if n % 2 == 0:
result.append(n * 2)
Pythonicなコード
result = [n * 2 for n in numbers if n % 2 == 0]
読みやすいか?
おわりに
悪口言うの向いてないみたいです。皆様も何かありましたら、コメントお願いします。