Pythonの欠点は何ですか?[閉まっている]


147

Pythonは最近大流行しているように見えますが、それは当然のことです。なぜなら、Pythonは本当に解決すべき新しい問題を与えられることを楽しんでいる言語だからです。しかし、賢者がかつて言ったように(実際に誰がそれを言ったのかわからないので、彼を賢者と呼ぶ;彼がその賢者であったかどうかはまったくわからない)、本当に言語を知ることはそのことを知っているだけではない構文、設計など、利点だけでなく、欠点もあります。完璧な言語はありません。一部の言語は他の言語よりも優れています。

だから、あなたの意見では、Pythonの客観的な欠点になります。

注:ここで言語比較を求めているわけではありません(つまり、C#はPythonよりも優れています... yadda yadda yadda)-より多くの客観的(ある程度)の言語機能は、適切に設計されているかどうか、あなたがそれに欠けているものなど。比較として別の言語を使用する必要がある場合、ただし他の言語では詳しく説明するのが難しい点を説明するためにのみ使用します(つまり、理解を容易にするため)


50
これは有用な主観的な質問であり、それを閉じるのは残念だと思います。
エリックウィルソン

25
python-fanboyがここにいるようです。これは、すべての反Python回答をただ投票するだけです。
zvrba

2
@TMN:それはまだ空白をトークンとして扱っているだけで、トークンを返すだけではありません。まさにPythonの文法もそうです。

9
@ロジャー:SOの慣習は、下票をコメントすることです。これは主観的な意見のサイトであるため、特に投票権を行使する理由はありません。コメントなし。だから、私は自分の「名前の呼びかけ」のそばに立っています。
zvrba

8
@zvrba:いつものように、Downvotesは依然として「役に立たない」という意味です。

回答:


109

私はPythonを定期的に使用していますが、全体的にはPythonは非常に優れた言語であると考えています。それにもかかわらず、完璧な言語はありません。私にとって個人的に重要な順に欠点を以下に示します。

  1. 遅いです。本当に遅いということです。多くの場合、これは重要ではありませんが、それは間違いなく、これらのパフォーマンスクリティカルなビットのために別の言語が必要になることを意味します。

  2. ネストされた関数は、外側のスコープの変数を変更できないという点で劣悪です。 編集: 私はまだライブラリのサポートのためにPython 2を使用しており、この設計上の欠陥は私をイライラさせますが、明らかに非ローカルステートメントのためにPython 3で修正されています。私が使用するライブラリが移植されるのを待つことができないので、この欠陥は永久に歴史の灰の山に送ることができます。

  3. ライブラリ/ジェネリックコードに役立ついくつかの機能が欠けているため、IMHOは不健全な極限まで単純化されています。私が考えることができる最も重要なものは、ユーザー定義の値型(これらはメタクラスの魔法で作成できると思いますが、試したことはありません)とref関数パラメーターです。

  4. 金属とは程遠い。スレッドプリミティブやカーネルコードなどを記述する必要がありますか?幸運を。

  5. Pythonが提供するダイナミズムのトレードオフとして、前もってセマンティックエラーをキャッチする能力の欠如は気にしませんが、実際にコードを実行することなく、構文エラーや変数名のタイプミスなどの愚かなことをキャッチする方法があればいいのにと思います。

  6. ドキュメントは、PHPやJavaのような強力な企業支援がある言語ほど優れていません。


60
@Casey、私は反対しなければなりません。インデックスは恐ろしいです- withステートメント、またはのメソッドを検索してみてくださいlist。チュートリアルでカバーされているものは、基本的には検索できません。MicrosoftのC ++のドキュメントを使用した方が幸運です。
マークランサム

17
約5-pyflakesを使用します。これらのエラーを正確にキャッチするために書かれています。
アレクサンダーソロヴィヨフ

4
速度に関して:PyPyの台頭により、多くのPythonユーザーは、組み込みのJITコンパイラーを備えたインタープリターを使用するだけで速度の問題に対処できるようになりました(現時点では、Python 3ユーザーとcpyextによって処理されないC拡張モジュールのユーザーこのオプションはありません)。
-ncoghlan

29
Pythonドキュメントを軽deしています。確かにそれらは最もきれいですが、多くの場合、文字列やリストのメソッドのように、多くの有用な情報が1ページにまとめられています。また、すべてのシーケンスタイプもまとめられています。この情報を検索するとき、私は巨大な本にたどり着き、私が欲しいものを見つけるためにページを検索しなければなりません。また、これらのページのインデックスは読みにくく、必要なセクションを特定するのが難しい場合もあります。
カーソンマイヤーズ

5
金属からの距離をどのように議論することができますか?Pythonはシステム言語であると主張していましたか?
マークカンラス

66

Pythonが変数の宣言と使用を区別できないことは嫌いです。それを実現するために静的型付けは必要ありません。「これは、私が意図的に宣言する変数であり、新しい名前を導入するつもりです。これはタイプミスではありません」と言う方法があると便利です。

さらに、私は通常、Python変数をライトワンススタイルで使用します。つまり、変数を不変として扱い、最初の割り当て後に変数を変更しません。リストの理解などの機能のおかげで、これは実際には非常に簡単であり、コードの流れを理解しやすくします。

ただし、その事実を文書化することはできません。Pythonには、フォームの上書きや変数の再利用を妨げるものは何もありません。

要約すると、言語に2つのキーワードがあります:varlet。どちらにも宣言されていない変数に書き込みを行うと、Pythonはエラーを発生させるはずです。さらに、let変数は読み取り専用として宣言しvarますが、変数は「通常」です。

この例を考えてみましょう:

x = 42    # Error: Variable `x` undeclared

var x = 1 # OK: Declares `x` and assigns a value.
x = 42    # OK: `x` is declared and mutable.

var x = 2 # Error: Redeclaration of existing variable `x`

let y     # Error: Declaration of read-only variable `y` without value
let y = 5 # OK: Declares `y` as read-only and assigns a value.

y = 23    # Error: Variable `y` is read-only

型はまだ暗黙的であることに注意してください(ただし、let変数は新しい値に再バインドできないため、変数はすべての意図と目的のために静的に型付けされますが、var変数は動的に型付けされます)。

最後に、すべてのメソッド引数は自動的にになりますlet。つまり、読み取り専用になります。一般的に、次のイディオムを除き、パラメーターを変更する正当な理由はありません。

def foo(bar = None):
    if bar == None: bar = [1, 2, 3]

これは、わずかに異なるイディオムに置き換えることができます。

def foo(bar = None):
    let mybar = bar or [1, 2, 3]

6
Pythonに「var」ステートメントがあればいいのに。あなたが述べる(非常に良い)理由に加えて、それはまた、あなたがすべての変数宣言を見つけるためにページをスキャンすることができるので、コードを読みやすくするでしょう。
ジョッキング

25
Python開発者が過去の教訓を無視したかのようです。1950年代に最初に犯した間違いは、変数を宣言せず、関数を宣言しないことです。見つけにくいタイプミスに起因するバグを見つけるのが難しいものは、1950年代に最初に作られた驚くほど十分なものでした。この言語の間違いは何度も何度も繰り返されています(後で修正されています)。変数を宣言することは大きな負担ではありません。それは私の尻を複数回保存しました。必然的にuse strict;use warnings;あらゆるサイズのスクリプトをperlで実行します。Pythonは、開発者からあまりにも多くのデバッグ支援を奪いました。
デヴィッドハンメン

19
@ David、Pythonに公平を期すために、割り当てられていない変数にアクセスしようとすると例外が発生します。宣言がない言語の多くは、何らかのデフォルト値を返します。その結果、Pythonのバージョンはそれらのバージョンよりもはるかに問題が少ないです。
ウィンストンイーバート

1
@yi_Hこの提案は、後方互換性を目的としたものではなく、実際の提案でもありませんでした。質問...よく、「パイソンの欠点は何ですか」、だった持っていないvarlet(または同様のメカニズム)が欠点です。言い換えると、私がPythonのデザイナーだったら、このようなことをしたでしょう。いえ、将来のバージョンでは可能性がありますが(に似た特殊なパッケージをロードする際に、これを含めます__future__)。、と言いますimport strict。ただし、構文上のハックが必要なため、これは発生しません…
コンラッドルドルフ

3
+1より優れた「機能的な」プログラミング機能を追加するため。
エヴァンプレイス

44

私の主な不満はスレッドです。これは、グローバルなインタープリターロックのために、多くの状況で(Java、Cなどと比較して)パフォーマンスが低下します(「Python GILの内部」(PDFリンク)トークを参照)

ただし、非常に使いやすいマルチプロセスインターフェイスがありますが、同じ数のプロセスとスレッドのメモリ使用量が重くなったり、多くの共有データがある場合は難しくなります。ただし、利点は、複数のプロセスで動作するプログラムを作成すると、スレッド化されたプログラムでは不可能な複数のマシンにまたがって拡張できることです。

私はドキュメントの批評に本当に反対します。それは、すべての主要言語ではないにしても、ほとんどの言語よりも優れており、優れていると思います。

また、pylintを実行しているランタイムバグの多くをキャッチできます。


2
パイリントの場合は+1。私はそれを知りませんでした。次回Pythonでプロジェクトを行うときは、試してみます。また、参照CPython実装の代わりにJythonを使用する場合、マルチスレッドは正常に機能するようです。OTOH JythonはCPythonよりもやや遅いため、目的を部分的に無効にすることができます。
dsimcha

3
スレッドは十分にサポートされていませんか?スレッドライブラリは、2.1以前から存在していました。
rox0r

2
スレッドのサポートがあることは知っていますが、JavaやCと比較して、GILはパフォーマンスを本当に低下させます。そのため、マルチプロセッシングモジュールがスレッドよりも優先されます。
cmcginty

2
あなたがそれを見つけることができれば、ドキュメントは良いです。Javaクラスのグーグルは、Pythonよりもはるかに簡単です。
ブレンダンロング

@Caseyスレッド化がサポートされているため、答えの文言を明確にしました。いくつかの奇妙なパフォーマンスを示しています(リファレンスとドキュメントへのリンクも追加)
dbr

28

おそらく、特定のクラスのランタイムエラーを引き起こす可能性がある静的型付けの欠如は、アヒル型付けが提供する追加の柔軟性に値しません。


5
これは正しいですが、C / Javaのような言語のコンパイラが行うエラーをチェックできるPyCheckerのようなツールがあります。
オリバーワイラー

24
動的型付けは、設計上の意思決定であり、欠点ではありません。
missingfaktor

14
Javaの弱点は、動的型付けの欠如と同じです。
MAK

12
@ missingfaktor、@ MAK、明らかにカモタイピングは意図された機能でした。しかし、ほとんどの設計決定には客観的な利点と欠点があります。追加されたコードの柔軟性は動的型付けの利点であり、潜在的な実行時エラーの追加のクラスは欠点です。主観的な部分は、機能に価値があるかどうかです。
ジェイコブ

6
静的型付けの欠如により、プログラマーはランタイムエラーのあるコードを記述しやすくなります。C#ではint foo = 4; Console.Write(foo.Length);コンパイルされないため、「Int32にはプロパティの長さはありません」というエラーが誤って公開ソフトウェアに侵入することはありません。Pythonでは、オプションのセカンダリツールを実行してそのようなエラーを探す場合を除き、オブジェクトの存在しないメンバーにアクセスするコードは、実行時エラーが発生するまで検出されない可能性があります。
ジェイコブ

27

Pythonのオブジェクト指向の部分は、「ボルトオン」のように感じます。すべてのメソッドに明示的に「自己」を渡す必要性全体は、OOPコンポーネントが明示的に計画されていなかったという症状です。また、別の答えで批判されたPythonの時々いぼなスコープルールも示しています。

編集:

Pythonのオブジェクト指向の部分が「ボルトで締められている」と感じるとき、私は時々、OOP側がかなり矛盾していると感じることを意味します。たとえば、Rubyの場合:Rubyでは、すべてがオブジェクトであり、使い慣れたobj.method構文を使用してメソッドを呼び出します(もちろん、オーバーロードされた演算子を除きます)。Pythonでは、すべてがオブジェクトでもありますが、関数として呼び出すメソッドもあります。すなわち、__len__長さを返すためにオーバーロードしますが、他の言語でよくlen(obj)知られている(一貫した)obj.length一般的な方法の代わりにそれを使用して呼び出します。この設計決定の背後には理由があることは知っていますが、私はそれらが好きではありません。

さらに、PythonのOOPモデルには、いかなる種類のデータ保護もありません。つまり、プライベートメンバー、保護メンバー、パブリックメンバーはありません。メソッドを使用___て、メソッドの前でそれらを模倣することができますが、それはちょっといです。同様に、Pythonはありません、かなりのいずれか、右OOPのメッセージパッシング様相を得ます。


17
selfパラメータは、他の言語が暗黙的に残すものを単に明示的にするだけです。これらの言語には、明らかに「自己」パラメーターがあります。

13
@Roger Pate:はい。ただし、「自己」の明示的な必要性は、いらいらするものです(そして、私は、漏れやすい抽象化だと主張します)。また、意図的な設計上の決定としてではありませんでしたが、Pythonの「奇妙な」スコープ規則のためです。この記事をすぐに見つけることはできませんが、Guido van Rossumから「self」パラメーターが必要な理由を説明するメールがあります。
mipadi

2
@Roger Pate:オブジェクト指向言語では、最初のパラメーターとしてターゲットを渡すことは、実装の詳細と見なすことができます。しかし、私のポイントは、それが良いアイデアかどうかではありません。ポイントはPythonで、それはだということであるないに配慮した設計の決定によるものではなく、スコーピングシステムのいぼを回避します。
mipadi

3
@mipadi:更新にはより良い推論があります(したがって、下票を削除します)が、len をオーバーロードする演算子と見なすと、Pythonのオブジェクト指向になります。Pythonがメッセージの受け渡しを間違っている方法の例や理由をご覧ください。

8
明示的なselfは、メソッドが単なる関数であるという事実の派生物です(そして、Winstonが指摘したように、暗黙的なローカル変数宣言)。その設計上の決定を好きではありませんが、実行時にオブジェクトとしてすべてにアクセスできる言語でOOPを「ボルトオン」と呼ぶのはばかげています。
ncoghlan

19

Pythonが気に入らないこと:

  1. スレッド化(既に言及されていることは知っていますが、すべての投稿で言及する価値があります)。
  2. 複数行の匿名関数はサポートされていません(lambda式を1つだけ含めることができます)。
  3. シンプルだが強力な入力読み取り機能/クラスの欠如(C ++およびCまたはJavaのようなcinまたは)。scanfScanner
  4. デフォルトでは、すべての文字列はUnicodeではありません(ただし、Python 3で修正されています)。

5
(2)に関しては、これはネストされた関数を持つ可能性によって相殺されると思います。
コンラッドルドルフ

3
@KonradRudolph複数行のラムダの代わりにネストされた関数を使用する私の主な問題は、読み取り順序が入れ替わることです。
CookieOfFortune

2
@wkschwartz:raw_inputと 'sys.stdin'はかなりベアボーンです。フォーマットされた入力の取得をサポートしていません(たとえば、 "%d:%d:%d"%(時間、分、秒)のようなものを時間内に読み込む)。これまでのところ、Pythonにはscanf(C)またはScanner(Java)の機能に近づくものはありません。
MAK

2
@limscoder:Javaでは、すべての文字列はデフォルトでUnicodeです。strクラスとunicodeクラスを分離する正当な理由はわかりません。私見、文字列とバイトの配列は、同じ抽象化によって表されるべきでありませ。文字列クラスは、テキストの格納と操作に使用する必要があります。その内部表現はあまり重要ではありません。文字列内の特定のバイトで切り捨て/置換/削除/挿入のようなことをしたくない-特定の文字でこれを行いたい。その区別を忘れがちで、英語以外の入力が与えられるとコードが爆発してしまいます。
MAK

1
@limscoder:簡単なUnicodeを表示する場合は、Tclを試してください。数年前にTclからPythonに切り替える必要がありましたが、少年はPythonのユニコードサポートが原始的であることに驚いていました。Tclではまったく見えず、Pythonでは大きな苦痛です。
ブライアンオークリー

18

可変データ型のデフォルト引数。

def foo(a, L = []):
    L.append(a)
    print L

>>> foo(1)
[1]
>>> foo(2)
[1, 2]

これは通常、いくつかの微妙なバグの結果です。(すべての関数呼び出しに使用する単一のオブジェクトを作成するよりも)デフォルトの引数が必要な場合は常に新しいリストオブジェクトを作成する方が良いと思います。

編集:それは大きな問題ではありませんが、ドキュメントで何かを参照する必要がある場合、それは一般に問題であることを意味します。これは必須ではありません。

def foo(a, L = None):
    if L is None:
        L = []
    ...

特に、それがデフォルトである必要があった場合。これは単に予期しない動作であり、多くの状況では役に立たない奇妙な動作です。


これについて多くの苦情がありますが、なぜ人々はデフォルトの引数として空のリスト(関数が変更する)を主張するのですか?これは本当に大きな問題ですか?すなわち、これは本当の問題ですか?
マーティンVilcans

8
それは、最も驚きの少ない原則に違反しています。関数のパラメーターが呼び出し間で生き残ることは期待できません。
aib

スクリプト言語であることの結果です。このバグに一度困惑するだけで、もう二度と困ることはありません。このバグを自分で理解することにより、実際にスクリプトを実行する言語であることを思い出させてくれます。そして、それは、言語がスクリプトの側面を隠すのに非常に優れているからです(正しく使用すると仮定します)。
ゾランパブロビッチ

好奇心から@ZoranPavlovic、なぜこれがスクリプト言語であることの結果なのですか?データがバインドされるとき、およびリストが可変であるために問題があるようです(これは通常良いことですが、一緒に組み合わせると悪い結果になります)。関数が呼び出されるたびに新しいリストを作成するのではなく、関数の作成時にデータをバインドすると、非スクリプト言語でも同じ問題が発生する可能性があります。
jsternberg

@aib:私はそうは思いません-他のすべてのPythonオブジェクトと同様に、ここのパラメーターはオブジェクトへのポインターです。この場合、オブジェクトは変更可能なオブジェクトであり、関数が宣言されると変数がバインドされます。このパラメーターは「呼び出し間で存続します」が、存続するのは可変オブジェクトへの参照です。
パトリックコリンズ

14

開発言語として非常に柔軟にするPythonの機能のいくつかは、C ++やJavaなどの言語でコンパイルおよびリンクプロセスによって実行される「プログラム全体」の静的分析に使用されるものによっても大きな欠点と見なされます。

  • ローカル変数の暗黙的な宣言

ローカル変数は、通常の割り当てステートメントを使用して宣言されます。つまり、他のスコープの変数バインディングでは、コンパイラーが明示的な注釈を取得する必要があります(外部スコープのグローバルおよび非ローカル宣言、インスタンススコープの属性アクセス表記)。これにより、プログラミング時に必要なボイラープレートの量が大幅に削減されますが、明示的な変数宣言を必要とする言語でコンパイラーによって処理されるチェックを実行するには、サードパーティの静的解析ツール(pyflakesなど)が必要です。

  • 「モンキーパッチ」がサポートされています

モジュール、クラスオブジェクト、さらには組み込みの名前空間の内容も、実行時に変更できます。これは非常に強力であり、非常に有用な多くのテクニックを使用できます。ただし、この柔軟性は、Pythonが静的に型指定されたOO言語に共通の機能を提供しないことを意味します。最も注目すべきは、インスタンスメソッドの「self」パラメータは暗黙的ではなく明示的であることです(「メソッド」はクラス内で定義する必要がないため、後でクラスを変更して追加できるため、特に実用的ではありません)インスタンス参照を暗黙的に渡す)および属性アクセス制御は、コードがクラスの「内部」または「外部」であるかどうかに基づいて容易に実施できません(その区別はクラス定義の実行中にのみ存在するため)。

  • 金属から遠い

これは他の多くの高レベル言語にも当てはまりますが、Pythonはほとんどのハードウェアの詳細を抽象化する傾向があります。CやC ++などのシステムプログラミング言語は、直接ハードウェアアクセスを処理するのに適しています(ただし、PythonはCPython拡張モジュールを介して、またはより移植性の高い、ctypesライブラリを介して)


12
  1. {} / begin-endの代わりに、コードブロックにインデントを使用します。
  2. 最新のすべての言語には、適切な字句スコープがありますが、Pythonはありません(以下を参照)。
  3. 混oticとしたドキュメント(Perl5のドキュメントと比較してください)
  4. 海峡ジャケット(それを行う唯一の方法があります)。

スコープの破損の例。通訳セッションからのトランスクリプト:

>>> x=0
>>> def f():
...     x+=3
...     print x
... 
>>> f()
Traceback (most recent call last):
  File "", line 1, in ?
  File "", line 2, in f
UnboundLocalError: local variable 'x' referenced before assignment

globalそしてnonlocalキーワードは、この設計の愚かさにパッチを適用するために導入されています。


2
スコープについては、python.org / dev / peps / pep-3104を参照して現在のメソッドの理由を理解するのがお勧めです。
ウィンストンイーバート

+1に同意します。だから、+ 1。
ジャス

34
一つの方法でそれを行うことは利点です。他の人のコードを読むとき、あなたは単一のステートメントを解読することはありません。イディオムが脳に組み込まれたら、すぐに認識できるはずです。
rox0r

9
@ rox0rに完全に同意します。「ストレートジャケット」は、あらゆる種類の構文戦争を防ぎます。
keithjgrant

8
正直に言うと、Pythonでglobalor nonlocalキーワードが必要になることはほとんどありません。私は仕事で毎日Pythonコードを書いているという事実にもかかわらず、めったにこの問題が存在することを忘れて、それが出てくる数回それを再グーグルしなければなりません。私にとって、グローバル変数(または、さらに悪いことに、外側の非グローバル変数)を変更する必要があるコードは、コードの匂いです。通常、(常にではないが)より良い方法があります。
ベン

11

私は、Pythonのオブジェクト指向構文this.method()と手続き型/関数型method(this)構文の組み合わせが非常に不安定だと感じています。

x = [0, 1, 2, 3, 4]
x.count(1)
len(x)
any(x)
x.reverse()
reversed(x)
x.sort()
sorted(x)

(メソッドではなく)多数の関数がグローバル名前空間に単にダンプされるため、これは特に悪いです:リスト、文字列、数値、コンストラクター、メタプログラミングに関連するメソッドは、すべてアルファベット順に並べられた1つの大きなリストに混在しています。

少なくとも、F#のような関数型言語には、すべての機能がモジュールで適切に名前空間付けされています。

List.map(x)
List.reversed(x)
List.any(x)

だから、彼らはすべて一緒ではありません。さらに、これはライブラリ全体で採用されている標準であるため、少なくとも一貫性があります。

関数メソッドの事をする理由は理解していますが、それをこのように混ぜることはいまだに悪い考えだと思います。少なくとも一般的な操作については、method-syntaxが守られていれば、私はずっと幸せです。

x.count(1)
x.len()
x.any()
x.reverse()
x.reversed()
x.sort()
x.sorted()

メソッドが変化しているかどうかに関係なく、オブジェクトのメソッドとして持つことにはいくつかの利点があります。

  • データ型の「一般的な」操作を検索する単一の場所:他のライブラリ/など。データ型に対してできる他の凝ったものがあるかもしれませんが、「デフォルト」操作はすべてオブジェクトのメソッドにあります。
  • Module呼び出すときにを繰り返し続ける必要はありませんModule.method(x)。上記の機能リストを例にとると、なぜList繰り返し声をかけ続けなければならないのですか?それがaであることを知っている必要があり、ListそのNavigation.map()関数を呼び出したくありません!x.map()構文を使用すると、DRYのままで、明確になります。

そしてもちろん、それは、グローバル名前空間にすべてを置く方法よりも優れています。現在の方法では物事を成し遂げることできないわけではありません。len(lst)名前空間がないため、かなり簡潔()です!メソッドよりも関数を使用する利点(デフォルトの動作など)を理解していますが、それでも好きではありません。

面倒です。そして、大きなプロジェクトでは、混乱があなたの最悪の敵です。


1
ええ... LINQスタイルが本当に恋しいです(LINQが最初にそれを実装したのではないでしょうが、最もよく知っています)リストの処理。
CookieOfFortune

1
len(x)をメソッドと考えないでください。「len」は関数です。Pythonには関数メソッドがあり、そのアプローチに問題はありません。適切な機能の欠如は、通常、多くの不必要なタイピングの原因です。
rbanffy

len()は機能であり、利点は何かを知っています。また、なぜそれが悪い考えだと思うのか、なぜグローバル関数が特に悪い考えだと思うのか、そしてなぜメソッドがあなたの機能を整理しスコーピングするのに便利な方法だと思うのかを
述べました

42(または43?)のキーワードが「大きな」数字だとは思いません。これにはdefclassなどの機能やその他の非関数呼び出しも含まれます。他のほとんどの一般的な言語の100以上と比較してください。また、次の行を検討してimport thisくださいNamespaces are one honking great idea -- let's do more of those!。Python名前空間を誤解するかもしれないと思う;)
ウェインワーナー

8

同質性の欠如。

Pythonは3.xで「with」キーワードが追加されるのを待たなければなりませんでした。どんなホモイコニック言語でも、ライブラリに簡単に追加できたはずです。

私が答えで見た他のほとんどの問題は、次の3つのタイプのいずれかです。

1)ツーリングで修正できるもの(pyflakesなど)2)実装の詳細(GIL、パフォーマンス)3)コーディング標準で修正できるもの(つまり、人々が望んでいない機能)

#2は言語の問題ではなく、IMO#1と#3は深刻な問題ではありません。


1
withPython 2.5から利用可能でしたfrom __future__ import with_statementが、私は時折、それは不幸なことがわかってきました、同意するように文if/ for/ print/などではなく、定期的な機能の「特別な」です
DBR

7

Pythonは非常に表現力に富んでいるので、私のお気に入りの言語ですが、それでも多くの間違いを犯さないようにします。私にはいらいらさせるものがまだいくつかあります。

  • 実際の匿名関数はありません。Lambdaは単一ステートメント関数にwith使用でき、ステートメントはRubyでコードブロックを使用する多くの場合に使用できます。しかし、状況によっては、物事が必要以上に不器用になります。(Javaの場合と同じくらい不器用ですが、それでも...)

  • モジュールとファイルの関係に多少の混乱があります。コマンドラインから「python foo.py」を実行することは、「import foo」とは異なります。Python 2.xでの相対的なインポートも問題を引き起こす可能性があります。それでも、Pythonのモジュールは、C、C ++、Rubyの対応する機能よりもはるかに優れています。

  • 明示的self。その理由のいくつかは理解していますが、Pythonを毎日使用していますが、忘れてしまうという間違いを犯しがちです。別の問題は、モジュールからクラスを作成するのが少し面倒になることです。明示的な自己は、他の人が不平を言っている限られた範囲に関連しています。Pythonの最小スコープは関数スコープです。必要に応じて関数を小さくしておけば、それ自体は問題ではなく、IMOは多くの場合よりクリーンなコードを提供します。

  • lenメソッドなど、いくつかのグローバル関数(これは実際には背後にあります)。

  • 重要なインデント。私は素晴らしいと思うアイデア自体ではありませんが、これは非常に多くの人々がPythonを試すことを妨げる唯一のものであるため、おそらくPythonはいくつかの(オプションの)開始/終了記号を使用する方が良いでしょう。それらの人々を無視して、私は完全にインデントの強制サイズで生きることができました。

  • JavaScriptではなく、Webブラウザの組み込み言語ではないこと。

これらの苦情の中で、私はそれが言語に追加されるべきだと思うので、私が十分に気をつけた最初の苦情だけです。最後のものを除いて、他のものはかなりマイナーです、それが起こったら素晴らしいでしょう!


+1 datetime.datetime.now()1つのプロジェクトが書き込めるときに書くのかdatetime.now、それから2つのプロジェクトを混ぜて書くのかは疑問に思われますが、Javaではファイルと同じ名前のモジュールはありませんでした(?)両方の使用が実践的で明示的であるときに、モジュールがファイルと混同しているように見える一般的な方法を見るとself、呼び出しは関数と同じ数の引数を持っていないので、私はまだ理解しようとします。そして、あなたはVM pythonが遅いと思うかもしれませんか?
ニクラスローゼンクランツ

明示的なselfキーワードの問題について。そのために良いPython IDEを使用することをお勧めしますか?Eclipse上のPyDevは、クラス内で記述していることが検出されると、関数シグネチャの自己部分を自動補完します。
ゾランパブロビッチ

5

Pythonは完全には成熟していません。現時点でのPython 3.2言語には、現在配布されているほとんどのパッケージとの互換性の問題があります(通常、Python 2.5と互換性があります)。これは現在、より多くの開発努力を必要とする大きな欠点です(必要なパッケージを見つける、互換性を検証する、互換性がある可能性のある不適切なパッケージの選択を検討する、最適なバージョンを取得し、3.2に更新するのに数日かかることがあります)何か役に立つことを始めてください)。

おそらく2012年半ばには、これはそれほど大きな欠点にはなりません。

ファンボーイに投票されたと思うことに注意してください。しかし、開発者の議論の中で、高レベルの開発者チームは同じ結論に達しました。

ある意味での成熟とは、チームがテクノロジーを使用して、隠れたリスク(互換性の問題を含む)を発生させずに非常に迅速に稼働できることを意味します。サードパーティのpythonパッケージと多くのアプリは、今日のほとんどのパッケージで3.2で動作しません。これにより、目の前の問題を解決する代わりに、技術自体を再実装、テスト、統合する作業が増えます==成熟度の低い技術。

2013年6月の更新:Python 3にはまだ成熟度の問題があります。チームメンバーは、必要なパッケージについて言及し、「2.6専用です」と言います(これらのケースのいくつかでは、ローカルソケットを介して、2.6で2.6のみのパッケージを使用する回避策を実装しました。ツールは3.2のままです。Python 3で書かれたpure-python wikiであるMoinMoinでさえありません。


2
成熟度の定義が設計上互換性のないバージョンと互換性ない場合にのみ同意します。
シェパン

3
pythonの2つの互換性のないストリームが問題であることに同意します(なぜそれが行われたのかは理解できますが)。
ウィンストンイーバート

ある意味での成熟とは、チームがテクノロジーを使用して、隠れたリスク(互換性の問題を含む)なしで非常に迅速に稼働できることを意味します。サードパーティのpythonパッケージと多くのアプリは、今日のほとんどのパッケージで3.2で動作しません。これにより、目の前の問題を解決する代わりに、技術自体を再実装、テスト、統合する作業が増えます==成熟度の低い技術。
ジョナサンクラインIEEE

2
次に、Python 2.xを使用します。ご存知のとおり...誰もが使用しているバージョン。または、パッケージのドキュメントを2秒間読んで、互換性のあるバージョンを確認してください。
jsternberg

2
「Python 3.0がしばらくリリースされたからといって、使用するバージョンを意味するわけではありません。Python3.0と2.xは同時に開発されています。将来的には、すべてのユーザーがpython 3.0ですが、今のところ2.xを使用するのが良いソリューションです」->それは500文字の言い方です。まだ成熟していません。
ジョナサンクラインIEEE

4

Pythonのスコープはひどく壊れているため、Pythonでのオブジェクト指向プログラミングは非常に厄介です。


8
例を挙げていただけますか?(私はあなたが正しいと確信していますが、私は例が欲しいです)
ウィンストン・エワート

24
私はPythonが好きですが、インスタンスプロパティとメソッドへのすべての参照の前に配置する必要があることは絶対に軽deself.しています。Pythonを使用してDSLを作成することは、Rubyで非常に簡単に行えるように不可能です。
アダムクロスランド

35
私は自分自身を厄介なものとは思わず、明示性が好きです。
ウィンストンイーバート

9
明示的な自己に関する大したことはわかりません。C ++、Java、およびDでは、多くの場合、人々は何らかの方法でメンバー変数を明示的にします。たとえば、アンダースコアを接頭辞として付けます。
dsimcha

7
宣言とは異なるメソッドでselfを使用します:def foo(self)but self.foo()。私はこの明示的な定義の混合物を見つけますが、暗黙的な舞台裏のものはあまりきれいではありません。
LennyProgrammers

4

Pythonについての不満:

  • ボルトオンOOP(これに関する詳細については、@ mipadiの回答を参照してください)
  • ラムダの壊れた実装
  • スコープの問題
  • 標準ライブラリに永続的なコレクションはありません
  • 組み込みDSLの快適性が低い

なぜ下票なのですか?
missingfaktor

私はダウンボーターではありませんが、オブジェクト指向がボルトで固定されている理由を説明できますか?Pythonには常にオブジェクト指向があり、それは言語の中核部分です。
デニス

@mipadiの答えをご覧ください。
missingfaktor


4

Pythonのアクセス修飾子は強制的ではありません。適切に構造化され、モジュール化されたコードを書くのが難しくなります。

これは@Masonの壊れたスコープの一部だと思います-この言語の一般的な大きな問題です。読みやすいはずのコードの場合、スコープ内にあるものとする必要があるもの、値をいつでも特定するのは非常に難しいようです-私は現在、これらの欠点のためにPython言語から移行することを考えています。

「全員が大人に同意している」からといって、特に複雑なプロジェクトで作業している場合、間違いを犯さず、強力な構造内でうまく機能しないという意味ではありません。インデントや意味のないアンダースコアでは十分ではないようです。


だからアクセス制御の欠如は悪いです...しかし、任意の非ローカル名前空間への変数書き込みの明示的なスコープも悪いですか?
-ncoghlan

@ncoghlan:1-この機能は、プロジェクトの構成方法に応じて、多くの現代言語で標準です。2-プログラマーの制御下にあります。3-それについて何がすばらしいかわからない-ほとんどのコンパイル済み言語/ IDEのいくつかのプロジェクト設定でスコープを簡単に制御できます。「全員が大人に同意している」場合、私たちは独自の決定を下し、特定の快適レベルに応じて範囲を調整できるはずです。
ベクトル

2
事は「強制アクセス制御」を求めて人々がPythonのような偉大な糊言語を作る非常にものの一つを取るために私たちを求めているということです。それは意図的だハード開発者はコードが後に使用される方法を制御します。強制アクセス制御を回避するためだけに、C ++およびJavaパターンの定型文はどれくらいありますか?これらの理由でPythonを使用しないことを選んだ人々は間違いなく理解できますが、厳密なテストに代わる静的な強制は決してありません。
ncoghlan

1
@ncoghlan-私にとってPythonの素晴らしいところは、構文と簡潔さの優雅さ-表現力です。そして、私が言ったように、スコーピングは、コード構造と組織よりも、行うべきでないことをいじるプログラマとは関係がありません。単純なユーティリティやスクリプトではなく、複雑なプロジェクトに取り組んでいます-コードは慎重にモジュール化および構造化する必要があります-アクセス修飾子は、それを保証する最も重要な方法の1つです。
ベクトル

1
また、コードのレビュー、トレーニング、結合分析などもあります。私にとって、強制アクセス制御は静的型付けと同じバケツに分類されます:それらは、正確性にある程度の追加の信頼性を提供するのに役立ちます(ただし、広範なテストの必要性を回避するには十分ではありません)が、開発生産性が高くなります。(実用レベルでは、クラス属性アクセス制御は、メソッドがクラスから取得される単なる通常の関数であるPythonのオブジェクトモデルにも適合しません。クラスの「内部/外部」境界は実際には存在しないため、施行)
-ncoghlan

3
  1. パフォーマンスは良くありませんが、pypyで改善しています。
  2. GILは、スレッド化を使用してコードを高速化することを防ぎます(ただし、これは通常、時期尚早な最適化です)。
  3. これは、アプリケーションプログラミングにのみ有用です。

しかし、それはいくつかの素晴らしい償還機能があります:

  1. RADに最適です。
  2. Cとのインターフェースが簡単です(CがPythonインタープリターを組み込むため)。
  3. とても読みやすく、
  4. 学ぶのは簡単です、
  5. 十分に文書化されており、
  6. バッテリーは実際に含まれています。標準ライブラリは巨大で、pypiには実質的にすべてのモジュールが含まれています。
  7. 健全なコミュニティがあります。

利点に言及したきっかけは何ですか?問題の質問。とにかく、アプリケーションプログラミングにのみ役立つとはどういう意味ですか?他にどんなプログラミングがありますか?特に何が良くないのですか?
シェパン

5
私はそれらが短所を上回ると思うので、利点をリストしました。PythonでLinuxカーネルモジュールを実装しようとしたことがありますか。
dan_waterworth

3

私はpythonを好みますが、頭に浮かぶ最初の欠点は、そのようなステートメントをコメントアウトすると、if myTest():CまたはJavaで行う必要のない実行済みブロック全体のインデントを変更する必要があることです。実際、Pythonではif節をコメントアウトする代わりに、次のようにコメントアウトし始めました: `if True:#myTest()したがって、次のコードブロックを変更する必要もありません。JavaとCはインデントに依存しないため、CとJavaでステートメントをコメントアウトしやすくなります。


1
インデントを変更せずにコードのブロックレベルを変更するには、CまたはJavaコードを真剣に編集しますか?
ベン

4
@Ben一時的に、はい...-
代替案

1
@ben同じ。
クリストファーマハン

2
に変更if something()するトリックを使用しif False and something()ます。別のトリックは、複数行の文字列を使用して「コメントアウト」することです。
マーティンVilcans

1
@Martin Of Course!Falseの場合...
クリストファーマハン

3

複数のディスパッチは、確立された単一ディスパッチタイプのシステムとうまく統合されず、あまりパフォーマンスがありません。

動的ロードは、POSIXのようなセマンティクスがメタデータ集約型の操作の致命的なスローダウンを引き起こす並列ファイルシステムでの大きな問題です。Python(numpy、mpi4py、petsc4py、およびその他の拡張モジュール)を65kコアにロードするだけで、25万コア時間を費やした同僚がいます。(シミュレーションは新しい科学的結果をもたらしたので、それだけの価値はありましたが、1バレル以上のオイルを燃やしてPythonを1回読み込むと問題になります。)静的にリンクできないため、dlopen一括ファイルシステムアクセスを実行するためにlibc-rtldにパッチを適用するなど、大規模な合理的なロード時間。


うわー、非常に技術的なようですが、このテーマに関する参考資料、例、ブログ投稿、記事はありますか?近い将来、このようなケースにさらされる可能性があるのだろうか。
ビンセント

AronはSciPy 2012で講演しました。これらdlopencollfsライブラリにあります。このリポジトリには、Asher Langtonのパスキャッシングに触発された追加のzipimportトリックも含まれています。私たちはより良い配布と論文に取り組んでいます。
ジェド

3
  • 広く使用されている非常に多くの非常に主流のサードパーティのライブラリとソフトウェアは、まったくPythonicではありません。いくつかの例:soaplib、openerp、reportlab。Critiqueは範囲外であり、広く使用されていますが、Pythonの文化を混乱させます(「1つあるべきです-できれば1つだけ-明白な方法」というモットーを傷つけます)。既知のpythonicの成功(djangoやtracなど)は例外のようです。
  • インスタンス、クラス、メタクラスの潜在的に無限の抽象化の深さは、概念的に美しくユニークです。しかし、それをマスターするには、インタープリター(Pythonコードが解釈される順序など)を深く知る必要があります。C#ジェネリックなど概念的により複雑な(IMHO)同様の黒魔術は、比例して広く知られ使用されているようですが、広く知られ使用されていません(または正しく使用されています)。
  • メモリとスレッドモデルを十分に把握するには、包括的な仕様がないため、Pythonを十分に経験する必要があります。通訳者のソースや経験のある癖を読んで、それらを修正する方法を発見したからかもしれません。たとえば、Javaのソフト参照およびファントム参照ではなく、強参照または弱参照のみがあります。Javaにはガベージコレクション用のスレッドがありますが、Pythonでガベージコレクションが行われるタイミングについての正式な回答はありません。Pythonコードが実行されていない場合、ガベージコレクションが発生しないことを確認できます。メモリを割り当てようとすると、おそらくガベージコレクションが発生する可能性があります。ロックされたリソースがリリースされなかった理由がわからない場合は注意が必要です(それについての私の経験はfreeswitchのmod_pythonでした)。

とにかく、Pythonは4年間私の主な言語です。ファンボーイ、エリート主義者、偏執狂者であることは、パイソン文化の一部ではありません。


+1。メモリとスレッドモデルの仕様は正しかった。ただし、スレッド上にあるJavaガベージコレクター(およびGCに関する他のほとんどすべて)であるFWIWは、Java言語またはVM仕様自体の側面ではなく、特定のJVMの実装の問題です。ただし、メインのSun / Oracle JVMは、GCの動作と構成可能性に関して広範囲に文書化されており、JVMチューニングに関する書籍全体が公開されています。理論的には、言語仕様に関係なく、同じ方法でCPythonをドキュメント化できます。
アンドリュージャンケ

2
  • 奇妙なOOP:
    • len(s)スルー__len__(self)およびその他の「特別な方法」
    • 他の特別なメソッド(__add__および__iadd__for +および+=)から派生できる特別な特別なメソッド
    • self 最初のメソッドパラメータとして
    • あなたは基本クラスのコンストラクタを呼び出すことを忘れることができます
    • アクセス修飾子なし(プライベート、保護...)
  • 定数定義なし
  • カスタム型には不変性がない
  • ギル
  • PythonとCが混在し、ビルドで問題が発生するパフォーマンスの低下(Cライブラリ、プラットフォームの依存関係の検索...)
  • 特にサードパーティのライブラリでの悪いドキュメント
  • Python 2.xと3.xの間の非互換性
  • 貧弱なコード分析ツール(JavaやC#などの静的に型付けされた言語に提供されるものと比較して)

5
個人的には、2.xと3.xの間の非互換性はPythonの最大の利点の1つだと思います。もちろん、それ欠点です。しかし、後方互換性を破る開発者の大胆さは、彼らが無限に悪口を持ち歩く必要がないことも意味します。より多くの言語でこのようなオーバーホールが必要です。
コンラッドルドルフ

0

「不変性」は、まさにそれが長所ではありません。私の知る限り、数字、タプル、文字列は不変であり、他のすべて(オブジェクト)は可変です。それを、すべてが不変(少なくともデフォルトでは)であるErlangやHaskellのような関数型言語と比較してください。

ただし、Immutabilityは同時実行性*で本当に輝いています。これはPythonの長所でもないため、少なくとも結果はそうです。

(* = nitpickersの場合:少なくとも部分的に並行する並行性を意味します。Pythonは「シングルスレッド」並行性では大丈夫だと思います。この場合、不変性はそれほど重要ではありません。並行性がなくても素晴らしい。))


0

明示的に並列構造が必要です。たいていの場合、次のようなリストの理解を書くとき

[ f(x) for x in lots_of_sx ]

要素が処理される順序は気にしません。時々、返される順序を気にしないこともあります。

私のfが純粋なPythonのときにCPythonがうまくいかなくても、このような動作は他の実装で使用するために定義できます。


//スレッドの束をスポーン//キューqueをすべてのスレッドに渡すque.extend([x for x in lots_of_sx])que.wait()#すべてのlots_of_sxがスレッドによって処理されるのを待ちます。
ゾランパブロヴィッチ

0

Pythonには、主に哲学的な理由により、末尾呼び出しの最適化はありません。これは、大きな構造での末尾再帰がO(n)メモリを消費する可能性があることを意味し(不要なスタックが保持されるため)、O(1)メモリを取得するループとして再帰を書き換える必要があります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.