1

fooクラスを作成して、意味を説明します。

class Foo:
    def __init__(self, fakevalue):
        self.fv = fakevalue

    @staticmethod
    def make_a_foo():
        return Foo(2)

    def try_change_foo_value(self):
        self = Foo.make_a_foo()
        print "in change function, self.fv:", self.fv

if(__name__ =='__main__'):
    foo_instance = Foo(1)
    print "foo_instance.fv:", foo_instance.fv
    foo_instance.try_change_foo_value()
    print "foo_instance.fv:", foo_instance.fv

私が期待する:

foo_instance.fv: 1
in change function, self.fv: 2
foo_instance.fv: 2

しかし、結果は次のとおりです。

foo_instance.fv: 1
in change function, self.fv: 2
foo_instance.fv: 1

自己の値はすでに変更されていることがわかりますが、インスタンスの値は変更されていません。なんで?そして、この問題を解決する方法は?

4

5 に答える 5

3

この場合、selfは呼び出し元インスタンスへのポインタです。でポインタを変更してもtry_change_foo_value、関数のパラメータを変更するのと同じです。メソッドの外部では効果がありません。

これを明確にするために、あなたは考えることができます

a.try_change_foo_value()の省略形としてFoo.try_change_foo_value(a)selfこれにより、を変更するとローカル変数が変更さaれ、呼び出し元は変更されないことが明らかになります。

それを修正するには、あなたがする必要があります

def try_change_foo_value(self):
    self.fv = 2

しかし、mgilsonが指摘しているように、言うのはもっとPythonicfoo_instance.fv = 2です。

foo_instance(だけでなく)の値を実際に変更したい場合fvは、メソッドではなく、他の場所で変更する必要があります(概念的にはほとんど意味がありません)。

于 2012-10-10T02:00:52.867 に答える
1

self単なる変数です。通常のメソッド(たとえば、@staticmethodまたは@classmethodで装飾されていない...)の場合、渡されるオブジェクトはインスタンスです。ただし、関数内では、必要selfなものに再バインドできますが、割り当てによって右側のオブジェクトへの新しい参照が作成されるため、変更は関数の外部に保持されません。その参照を返さない限り、より広いスコープを持つオブジェクトに保存すると、関数が終了するとスコープ外になり、二度と聞かれることはありません(参照/ハンドルがなくなったため)。

通常の関数を検討してください。

def foo(x):
    x = 2

a = 1
foo(a)
print a #prints 1, not 2

これは実際には違いはありません。

于 2012-10-10T02:03:11.633 に答える
0

メソッドtry_change_foo_value内のコンテナ「self」を変更しています。selfはパラメーターとして渡されていることに注意してください。これは、変数self内の参照を変更できることを意味します。ただし、発信者から渡された参照を変更することはできません。Javaで考えてみてください。

public void changeIt(Foo foo) {
    foo = new Foo(2);
}

電話したら

Foo bar = new Foo(1);
.changeIt(bar);

バーはまだ「新しいFoo(1)」であることが期待できます。

于 2012-10-10T02:03:03.797 に答える
0

ではtry_change_foo_valueselfインスタンスとして開始しますが、割り当て時に変更します。のを印刷することidでこれを確認できselfます。

class Foo:
    def __init__(self, fakevalue):
        self.fv = fakevalue

    @staticmethod
    def make_a_foo():
        return Foo(2)

    def try_change_foo_value(self):
        print 'Originally, id(self) = %s' % id(self)
        self = Foo.make_a_foo()
        print 'After assignment, id(self) = %s' % id(self)
        print "in change function, self.fv:", self.fv

if __name__ =='__main__':
    foo_instance = Foo(1)
    print "foo_instance.fv:", foo_instance.fv
    foo_instance.try_change_foo_value()
    print "foo_instance.fv:", foo_instance.fv

に注意してくださいid

foo_instance.fv: 1
Originally, id(self) = 4299779608
After assignment, id(self) = 4299779680
in change function, self.fv: 2
foo_instance.fv: 1
于 2012-10-10T02:08:05.470 に答える
0

Pythonでの割り当てについては非常に簡単なルールがあります。Pythonで名前を割り当てると、その名前は、割り当てたばかりのオブジェクトを参照するようになります割り当ての前に名前が参照したオブジェクトを実際に変更することはありません。

これの単純な結果は、その行self = Foo.make_a_foo()では、それ以前に何があったかは完全に無関係であるということです。selfクラスとインスタンスについて話しているという事実は、これとは関係ありません。self以前は何であれself、新しいFooオブジェクトを参照する名前が付けられました。

名前は、オブジェクトを取得するための単なるハンドルであることを忘れないでください。特定のオブジェクトは、任意の時点で0、1、または多くの名前で参照できます。割り当ては、オブジェクトではなく、名前に影響を与える操作です。オブジェクトを参照する名前を変更してオブジェクトを変更する方法はありません。

foo_instance = Foo(1)
print "foo_instance.fv:", foo_instance.fv
foo_instance.try_change_foo_value()
print "foo_instance.fv:", foo_instance.fv

上記がを呼び出すfoo_instance = Foo(1)と、名前foo_instanceは新しいオブジェクトを参照します。を呼び出すと、その同じオブジェクトにメソッドのスコープ内でfoo_instance.try_change_foo_value()追加の名前が付けられます。selfその名前を変更して新しいオブジェクトを参照する場合、元のオブジェクト、またはその元のオブジェクトを参照している名前foo_instanceには影響しません。

これはとても良いことです!そうしないと、関数を呼び出していくつかのオブジェクトを渡すたびに、関数が独自のローカル変数に割り当てるすべての割り当てによって、変数が参照しているものが変更されます。

于 2012-10-10T02:22:21.080 に答える