0

Pythonプールにつま先を浸しただけです。クラスと名前空間がどのように相互作用しdel、スコープからものを削除するか、そしてそのすべての長所を理解しています。

私の質問は簡単です。単純な「helloworld」(Pygame)アプリを作成しましたが、重大な間違いを犯しました(以下の単純なケース)。

class Cat:
  __name = ""
  def __init__(self, newName):
    __name = newName
  def meow(self):
    print "Hi from {0}".format(self.__name)

c = Cat("Mittens")
c.meow(); # prints: "Hi from "

後から考えると、私の間違いは明らかです。私のメソッド(コンストラクター、ここでは具体的には)で、値をto__nameではなくに割り当てました__self.name(ちなみに、これはマングルされてプライベートである必要があります)。

私はそれがどのようにそしてなぜ機能するのかさえ理解しています-それはJava/C#の静的スコープのようなものです。

私が理解していないのは、この種のトリッキーなエラーを回避する方法です。これは明白で簡単であり、私の場合、結果は何もありませんでした。物事はうまくいくはずでしたが、何も起こりませんでした。

Python開発者はこの問題をどのように回避しますか?それは非常に一般的であるように思われます。

4

2 に答える 2

2

この場合、__nameクラスの名前空間に追加することは絶対に避けます。__nameは、初期化子 ( ) によって無条件に設定される (と想定される)ため__init__、クラス レベル を持つ意味はありません__name

例えば:

class Cat:
  def __init__(self, newName):
    __name = newName
  def meow(self):
    print "Hi from {0}".format(self.__name)

c = Cat("Mittens")
c.meow() # prints: "Hi from "

コードを実行すると、AttributeErrorこの種のバグを検出するのに役立つ が得られます。

つまり、__init__コード内の の目的は、を介し__nameて初期化される ( ) 新しいインスタンスに設定することです。コードでは、クラスを設定することで「セーフティ ネット」を提供しています。Python では、インスタンスで属性が見つからない場合、クラスで検索されます。ただし、この「セーフティ ネット」は実際にはこの場合は悪いことです。バグを追跡するために使用できる例外ではなく、予想とは異なる動作が発生します。selfself.__name = newName__name


補足として、インスタンスの属性アクセスが機能する方法 ( のような興味深いものを除いて__getattribute__) は、python が最初にインスタンスで属性を検索し、次にクラスを検索してから、クラスのメソッド解決順序 (これは古いスタイルのクラスと新しいスタイルのクラスでは異なります)。

于 2013-03-08T20:21:48.327 に答える
1

pep8pylintpyflakesflake8などの静的分析ツールは、ある程度役立ちます。たとえば、pyflakesあなたのコードについて文句を言うでしょう (という名前のファイルに置かれますstack_overflow-2013-03-08.py):

$ pyflakes stack_overflow-2013-03-08.py
stack_overflow-2013-03-08.py:8: local variable '__name' is assigned to but never used

しかし、優れた一連のテストに勝るものはありません。言うまでもなくCat.meow、機能の範囲を合理的にカバーするテストがあれば、この問題を正しくキャッチできたはずです。

于 2013-03-08T20:34:58.297 に答える