7

これは、私が遭遇した問題を示すために作成した非常に単純なコードです。ここで起こっていることは、同じクラスの 2 つの異なるインスタンスを作成していますが、一方の属性を変更すると、もう一方のインスタンスの対応する属性が変更されるということです。これがなぜなのかわかりません。これは Python では普通のことですか、それとも完全に台無しになっている何かに遭遇していますか?

class exampleClass(object):

    attribute1=0
    attribute2="string"

x=exampleClass
x.attribute1=20
x.attribute2="Foo"

y=exampleClass
y.attribute1=60
y.attribute2="Bar"

print("X attributes: \n")
print(x.attribute1)
print(x.attribute2)

print("Y attributes: \n")
print(y.attribute1)
print(y.attribute2)

コンソールから出てきたプログラムは次のようになります。

>>> 
X attributes: 

60
Bar
Y attributes: 

60
Bar
>>> 

私はそれが言うべきだと思います:

X attributes:

20
Foo
Y attributes:

60
Bar

私は何を間違っていますか?

4

4 に答える 4

9

インスタンス属性が必要な場合は、クラス属性を作成しています。これを使って:

class exampleClass(object):
    def __init__(self):
        self.attribute1 = 0
        self.attribute2 = "string"

また、exampleClass のインスタンスを作成していないため、これが必要です。

x = exampleClass()
y = exampleClass()

あなたのコードは、クラスに新しい名前を使用し、その属性を変更するだけです。

于 2012-06-26T23:41:52.113 に答える
5

属性をクラス属性にしました。これは、クラスのオブジェクトではなく、クラス自体にスコープが設定されていることを意味します。

オブジェクトスコープが必要な場合は、次のようにすることができます。

class exampleClass(object):
        def __init__(self):
            self.attribute1=0
            self.attribute2="string"

x = exampleClass()
y = exampleClass()

次に、オブジェクトの属性値を変更すると、そのクラスのすべてのオブジェクトではなく、その特定のものにのみ影響します。

于 2012-06-26T23:43:25.580 に答える
3

わかりやすいように修正しました。

あなたが持っているコードでは、変数 x と y がクラス定義を参照するようにしているという問題があります.

x = exampleClass

Now は、x がクラス定義を指すようになったことを意味します。exampleClass の変数として attribute1 があるので、これを行うことができるので興味深いです。

x.attribute1 = 3

今、あなたが次のことをしたとします:

exampleClass.attribute1

最初に設定した 0 ではなく、3 が表示されます。

クラスのオブジェクトをインスタンス化するには、次のことを行う必要があります。

x = exampleClass()
y = exampleClass()

現在、両方の変数がそれぞれ独自の属性を持つ新しいオブジェクトを参照しています。

x.attribute1 = 219

次に、y.attribute1 が変更されていないことがわかります:) クラスと関数の名前を使用することは、Python では定義への参照として一般的です。したがって、オブジェクトをインスタンス化する場合は必ず括弧を使用してください。関数を呼び出したい場合は、必ず括弧も使用してください。そうしないと、名前を使用すると定義への参照になります。

ただし、Ned Batchelder の回答 (およびその他の回答) を読むことをお勧めします。これは、 init関数を使用してそのようにインスタンス変数を作成する必要があるためです。

しかし、全体としては Object クラスから継承されるため、この方法でインスタンス (括弧付き) などが作成されると想定できます。そのため、「自己」がなくてもインスタンス変数である必要があると信じているため、オブジェクトの値を変更できます。

于 2012-06-26T23:42:56.637 に答える
2

Python では、クラスもオブジェクトです。したがって、それらは変数に割り当てられ、他のオブジェクトと同じように独自の属性を持つことができます。

ブロックでバインドするすべての名前classは、作成されるクラスの属性になります。それらは、そのクラスの将来のインスタンスの属性ではありません。しかし、インスタンスから属性を読み取ろうとして、インスタンスにその属性がない場合、Python はデフォルトでインスタンスのクラスの属性を調べ、見つかった場合はそれを返します。これが実際に Python でメソッドが機能する方法です。それらはクラスの単なる属性であり、インスタンス (存在しない場所) からそれらを取得しようとすると、クラスを調べることで見つかります。

それを念頭に置いて、あなたのプログラムはあなたが思っていることをしません。

class exampleClass(object):

    attribute1=0
    attribute2="string"

exampleClassここでは、 と の 2 つの属性attribute1を持つという名前のクラスを作成しましたattribute2。それらはインスタンス属性ではありません。これは、Python を学習している人々によくある間違いです。単純な例では、インスタンス属性であるかのように機能するように見えることが多いため、これについて自分自身を訓練する必要があります。ブロックで名前をバインドするclassと、クラス オブジェクトに属性が作成されます。インスタンス属性を作成する唯一の方法は、インスタンスが存在するときにそのインスタンスへの参照を取得し、そのインスタンスに属性を割り当てることです。Python は、__init__これを行う場所としてメソッド (インスタンスの作成時に呼び出される) を提供します。

したがって、基本的な経験則は次のとおりです。クラス ブロックで定義された名前はクラス オブジェクトの属性であり、selfinの属性として割り当てられた名前__init__は、そのクラスのすべてのインスタンスの属性です。

あなたの混乱は、別の問題によってさらに悪化します。

x=exampleClass
x.attribute1=20
x.attribute2="Foo"

クラスは Python の他のすべてのものと同様にオブジェクトであるため、これは完全に合理的な Python コードですが、思ったようには実行されません。クラスのインスタンスを実際に作成していません。そのためには、のようにクラスを呼び出す必要がありますexampleClass()。生の名前exampleClassは単にクラス オブジェクト自体を参照するだけなので、その名前をそのオブジェクトにバインドし、xその属性の一部を割り当てただけです。当然、クラス オブジェクトにもバインドyし、 を介してそのオブジェクトに属性を割り当てるyと、 によって参照されるオブジェクトxが影響を受けます (同じオブジェクトです)。

于 2012-06-27T00:24:32.823 に答える