web-dev-qa-db-ja.com

__init __()の内部と外部の変数の違い

名前のほかに、これらのクラス間に違いはありますか?

class WithClass ():
    def __init__(self):
        self.value = "Bob"
    def my_func(self):
        print(self.value)

class WithoutClass ():
    value = "Bob"

    def my_func(self):
        print(self.value)

変数valueの宣言に__init__メソッドを使用する場合と使用しない場合、違いはありますか?

私の主な心配は、それが将来私にさらなる問題を引き起こすとき、私はそれを1つの方法で使用することです。

167
Teifion

__init__の外部で設定された変数は、クラスに属します。それらはすべてのインスタンスで共有されます。

__init__(および他のすべてのメソッド関数)内で作成され、self.で始まる変数は、オブジェクトインスタンスに属します。

204
S.Lott

自己なし

いくつかのオブジェクトを作成します。

class foo(object):
    x = 'original class'

c1, c2 = foo(), foo()

C1インスタンスを変更できますが、c2インスタンスには影響しません。

c1.x = 'changed instance'
c2.x
>>> 'original class'

ただし、fooクラスを変更すると、そのクラスのすべてのインスタンスも変更されます。

foo.x = 'changed class'
c2.x
>>> 'changed class'

ここでPythonスコープがどのように機能するかに注意してください:

c1.x
>>> 'changed instance'

自己あり

クラスを変更してもインスタンスには影響しません。

class foo(object):
    def __init__(self):
        self.x = 'original self'

c1 = foo()
foo.x = 'changed class'
c1.x
>>> 'original self'
70
northben

このスレッドと このスレッド (これを参照する)で読んだ応答に何かを追加したいと思います。

免責事項:この発言は、私が実行した実験からのものです

__init__以外の変数:

実際、これらはstaticクラス変数であるため、クラスのすべてのインスタンスにアクセスできます。

__init__内の変数:

これらのinstance variablesの値は、手元のインスタンスにのみアクセス可能です(self参照を介して)

私の貢献

static class variablesを使用する際にプログラマが考慮しなければならないことの1つは、instance variablesself参照を介してstaticクラス変数にアクセスしています。

説明

以前は、変数を宣言する両方の方法はまったく同じだと思っていました(私は愚かな)、それは、self参照を介して両方の種類の変数にアクセスできるからでした。私が問題に遭遇したとき、私は今トピックを研究し、それをクリアしました。

self参照を介してstaticクラス変数にアクセスする際の問題は、staticクラス変数のみが参照されることです。instance variableは同じ名前ではなく、さらに悪いことに、static class variableを再定義しようとしているinstance variableが作成され、以前にアクセス可能なstaticクラス変数がシャドウされるため、self参照を介して機能しません。 /。

この問題を回避するには、クラスの名前を通じて常にstatic class variablesを参照する必要があります。

#!/usr/bin/env python

class Foo:
    static_var = 'every instance has access'

    def __init__(self,name):
        self.instance_var = 'I am %s' % name

    def printAll(self):
        print 'self.instance_var = %s' % self.instance_var
        print 'self.static_var = %s' % self.static_var
        print 'Foo.static_var = %s' % Foo.static_var

f1 = Foo('f1')

f1.printAll()

f1.static_var = 'Shadowing static_var'

f1.printAll()

f2 = Foo('f2')

f2.printAll()

Foo.static_var = 'modified class'

f1.printAll()
f2.printAll()

出力

self.instance_var = I am f1
self.static_var = every instance has access
Foo.static_var = every instance has access
self.instance_var = I am f1
self.static_var = Shadowing static_var
Foo.static_var = every instance has access
self.instance_var = I am f2
self.static_var = every instance has access
Foo.static_var = every instance has access
self.instance_var = I am f1
self.static_var = Shadowing static_var
Foo.static_var = modified class
self.instance_var = I am f2
self.static_var = modified class
Foo.static_var = modified class

これが誰かに役立つことを願っています

12
alejandro

s.Lottの応答に加えて、クラス変数はメタクラスnewメソッドに渡され、メタクラスが定義されているときに辞書を介してアクセスできます。そのため、クラスが作成およびインスタンス化される前であっても、クラス変数にアクセスできます。

例えば:

class meta(type):
    def __new__(cls,name,bases,dicto):
          # two chars missing in original of next line ...
          if dicto['class_var'] == 'A':
             print 'There'
class proxyclass(object):
      class_var = 'A'
      __metaclass__ = meta
      ...
      ...
5
Neil
class User(object):
    email = 'none'
    firstname = 'none'
    lastname = 'none'

    def __init__(self, email=None, firstname=None, lastname=None):
        self.email = email
        self.firstname = firstname
        self.lastname = lastname

    @classmethod
    def print_var(cls, obj):
        print ("obj.email obj.firstname obj.lastname")
        print(obj.email, obj.firstname, obj.lastname)
        print("cls.email cls.firstname cls.lastname")
        print(cls.email, cls.firstname, cls.lastname)

u1 = User(email='abc@xyz', firstname='first', lastname='last')
User.print_var(u1)

上記のコードでは、Userクラスには3つのグローバル変数があり、それぞれの値は「なし」です。 u1は、このクラスをインスタンス化して作成されたオブジェクトです。メソッドprint_varは、クラスUserのクラス変数とオブジェクトu1のオブジェクト変数の値を出力します。以下に示す出力では、クラス変数User.emailUser.firstname、およびUser.lastnameのそれぞれの値は'none'ですが、オブジェクト変数u1.emailu1.firstnameおよびu1.lastnameの値は'abc@xyz''first'および'last'です。

obj.email obj.firstname obj.lastname
('abc@xyz', 'first', 'last')
cls.email cls.firstname cls.lastname
('none', 'none', 'none')
1

クラスとインスタンスの辞書を追跡する場合、これは非常に簡単に理解できます。

class C:
   one = 42
   def __init__(self,val):
        self.two=val
ci=C(50)
print(ci.__dict__)
print(C.__dict__)

結果は次のようになります。

{'two': 50}
{'__module__': '__main__', 'one': 42, '__init__': <function C.__init__ at 0x00000213069BF6A8>, '__dict__': <attribute '__dict__' of 'C' objects>, '__weakref__': <attribute '__weakref__' of 'C' objects>, '__doc__': None}

ここですべての結果を設定しましたが、インスタンスci dictが{'two': 50}になり、クラスディクショナリに'one': 42キー値ペアが含まれることが重要です。

これが特定の変数について知っておくべきことのすべてです。

0
prosti