4

私はC++の世界から来ているので、これは何時間も私を悩ませました。私はついに何が起こっているのかを知りましたが、なぜこれがデフォルトの動作であるのかわかりません。言語がこのように設計されている理由を理解したいと思います。

インスタンス変数が必要memでした。だから私はこれを試しました:

class x(object):
   mem = []

obj = x()
obj.mem.append(1)
print(obj.mem)
objTWO = x()
objTWO.mem.append(2)
print(objTWO.mem)

これを印刷します:

[1] 

[1, 2]

一方:

class x(object):

    def __init__(self):
        self.mem = []

obj = x()
obj.mem.append(1)
print(obj.mem)
objTWO = x()
objTWO.mem.append(2)
print(objTWO.mem)

プリント

[1]

[2]

なぜ最初がデフォルトの動作になるのでしょうか?ここでの直感は何ですか?主流のオブジェクト指向言語の数とは逆です(static静的変数が必要であると明示的に言う、トップケースのキーワードを導入しています)?Pythonの初心者にとって、これは驚きです。

また、同じ名前のインスタンス変数とクラス変数を持つことが許可されているようです。

class x(object):
    mem = []

    def __init__(self):
        self.mem = []

何が印刷されるかを理解するためにこれを実行する必要があります。推測すらできない!

4

2 に答える 2

8

直感的には、Pythonでは、クラス自体を含め、すべてがオブジェクトです。Pythonには「static」キーワードのようなものはありません。オブジェクトであるクラスがあり、それらのクラスには属性があります。クラス定義に表示されるものはすべてクラス属性です。これには、メソッドと他の種類の属性の両方が含まれます。

この設計の利点は、単純さと一貫性です。パブリック属性とプライベート属性、または静的属性と非静的属性の区別はありません。クラス属性とインスタンス属性の違いは、クラスコンストラクターによって自然に明らかになります。が__init__(を介して間接的に)呼び出されると、パラメータClassName(params)を介してクラスの新しいインスタンスを受け取り、そのインスタンスを直接変更します。selfすでに定義されている構成を介して、すべてが明示的に行われます。インスタンスが作成されたときに何が起こっているかを確認するために、新しい構文や新しいキーワードを理解する必要はありません。

次に、理解する必要があるのは、属性ルックアップ用のPythonのモデルだけです。PATHほとんどのシェルの解像度とほぼ同じように機能します。たとえば、bashでは、コマンド(ls)を実行すると、パスの最初のエントリが検索され、次に2番目のエントリが検索され、見つかったコマンドの最初のバージョンが実行されます。ただし、この場合、パスは次のようになります(少なくとも単一継承の単純な場合)。

instance; class; superclass; superclass; ... and so on

これは、cまたはc++のネストされたスコープでの名前解決とそれほど違いはありません。あなたは文句を言います:

さらに悪いことに、同じ名前のインスタンス変数とクラス変数を持つことが許可されているようです。

int i;しかし、それは、cを使用してブロック内で定義し、内部ブロックを作成してから、int i;元のブロックをマスクする別のブロックを定義できるという事実よりも、本当に紛らわしいですか?

于 2012-11-14T19:11:18.073 に答える
-1

直感に反することに同意しますが、エイリアシング関数という良い使い方があります。

これは私がしばらく前に書いたライブラリからのもので、長さを編集したものです

...
class UndrawnTurtle():
    """Acts just like the turtle package, but without bringing up a window to show it."""
...

    def forward(self, distance):
        angle_radians = math.radians(self.angle)

        self.x = self.x + math.cos(angle_radians) * distance
        self.y = self.y + math.sin(angle_radians) * distance

        self._visit()

...
    # Now for some aliases. Everything that's implemented in this class
    # should be aliased the same way as the actual api.
    fd = forward
...
于 2012-11-14T19:02:56.453 に答える