6

静的言語(java / c#)からPythonのような動的言語に移行する人にとっての一番の落とし穴は何ですか?

方法はすばらしいようですが、メソッドの名前を変更したり、パラメーターを追加/削除したりするのは非常に危険です。

各メソッドのテストを作成する唯一のソリューションはありますか?

4

3 に答える 3

3

「各メソッドのテストを作成する唯一のソリューションはありますか?」

Javaで各メソッドのテストを作成しなかったと言っていますか?

Javaで各メソッドのテストを作成した場合、-まあ-何も変わりませんね。

メソッドの名前を変更するのはとても危険なようです!

正しい。しないでください。

パラメータの追加/削除はとても危険なようです!

何?オプションのパラメータについて話しているのですか?もしそうなら、Javaで複数のオーバーロードされた名前を持つことは危険で混乱しているように思われます。オプションのパラメータを使用する方が簡単なようです。


SOで最も一般的なPythonの質問を検索すると、慢性的な質問であることがわかります。

  • を更新する方法PYTHONPATH

  • いくつかのランダムな浮動小数点計算が数学的な抽象化が示すのと同じではない理由。

  • Python 3を使用し、Python2チュートリアルのコードを入力します。

  • Pythonに超複雑protectedな宣言がない理由。privatepublic

  • Pythonに列挙型がない理由。

一番の慢性的な問題は、関数のデフォルト値として可変オブジェクトを使用しているようです。単にこれを避けてください。

于 2010-09-13T19:33:28.977 に答える
2

Pythonを最初に試したときに私を驚かせたいくつかのこと(主にJavaのバックグラウンドから来ています):

  1. Pythonicコードを記述します。古いJava/Cの方法ではなく、Pythonに推奨されるイディオムを使用してください。これは単なる見た目の問題や独断的な問題ではありません。Pythonicコードは、実際にはCのようなコードよりも実際には非常に高速です。実際のところ、IMHOの「Pythonは遅い」という概念の多くは、経験の浅いコーダーがPythonでJava / Cをコーディングしようとして、パフォーマンスに大きな打撃を与え、Pythonがひどく遅い。リスト内包表記を使用し、可能な限りマップ/フィルター/リデュースします。

  2. 関数は本当にオブジェクトであるという考えに慣れてください。それらをコールバックとして渡し、関数に関数を返すようにし、クロージャについて学びます。

  3. おっしゃるように、メソッドの名前を変更するなど、Pythonで実行できるクールでほとんど魔法のようなことがたくさんあります。これらはPythonの機能を披露するのに最適ですが、必要がなければ実際には必要ありません。確かに、S。Lottが指摘したように、危険と思われることは避ける方がよいでしょう。

于 2010-09-13T20:04:58.443 に答える
2

一番の落とし穴は、静的に型付けされたコードを動的言語で書き込もうとしていることだと思います。

識別子を使用して文字列を指し、次にコードの自己完結型セクションのリストを指すことを躊躇しないでください

keys = 'foo bar foobar' # Imagine this coming in as an argument
keys = keys.split() # Now the semantically chose name for the argument can be 
                    # reused As the semantically chosen name for a local variable

関数を通常の値のように扱うことを躊躇しないでください。次のパーサーを取ります。すべてのヘッダータグを同じように扱い、ulタグをolタグのように扱いたいとします。

class Parser(HTMLParser):
    def __init__(self, html):
        self.feed(html)

    def handle_starttag(self, tag, attrs):
        parse_method = 'parse_' + tag    
        if hasattr(self, parse_method):  
            getattr(self, parse_method)(attrs)


    def parse_list(self, attrs):
        # generic code

    def parse_header(self, attrs):
       # more generic code

    parse_h1 = parse_h2 = parse_h3 = parse_h4 = parse_h5 = parse_h6 = parse_header
    parse_ol = parse_ul = parse_list

handle_starttagこれは、Javaのような言語のメソッドで、同じメソッドにマップされるタグを追跡することにより、あまり一般的でないコードを使用することで実行できますが、divタグを処理する場合は、それをディスパッチロジックに追加する必要があります。 。ここでは、メソッドを追加するだけで、準備は完了parse_divです。

タイプチェックしないでください!ダックタイピング!

def funtion(arg):
    if hasattr(arg, 'attr1') and hasattr(arg, 'attr2'):
         foo(arg):
    else:
         raise TypeError("arg must have 'attr1' and 'attr2'")

とは対照的にisinstance(arg, Foo)。これにより、とを使用して任意のオブジェクトを渡すことができattr1ますattr2。これにより、たとえば、デバッグ目的でオブジェクトにラップされたトレースクラスを渡すことができます。Java AFAIKでそれを行うには、クラスを変更する必要があります。

THC4kが指摘しているように、これを行う別の(よりPython的な)方法はEAPFイディオムです。できるだけ早くエラーをキャッチしたいので、これは好きではありません。ただし、コードがめったに失敗しないことを期待する場合は、より効率的です。私がPythonの書き方を知っていると彼らが考えるのをやめるでしょうが、私がそれを好きではないことを誰にも言わないでください。THC4kの好意による例を次に示します。

try: 
    foo(arg): 
except (AttributeError, TypeError): 
    raise InvalidArgumentError(foo, arg)

AttributeErrorをキャッチする必要があるかどうか、またはそれらを処理する方法を知っている場所に伝播させるかどうかについてのトサップですTypeErrorが、これは単なる例なので、飛ばします。

于 2010-09-13T20:06:45.147 に答える