名前のほかに、これらのクラス間に違いはありますか?
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つの方法で使用することです。
__init__
の外部で設定された変数は、クラスに属します。それらはすべてのインスタンスで共有されます。
__init__
(および他のすべてのメソッド関数)内で作成され、self.
で始まる変数は、オブジェクトインスタンスに属します。
自己なし
いくつかのオブジェクトを作成します。
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'
このスレッドと このスレッド (これを参照する)で読んだ応答に何かを追加したいと思います。
免責事項:この発言は、私が実行した実験からのものです
__init__
以外の変数:
実際、これらはstaticクラス変数であるため、クラスのすべてのインスタンスにアクセスできます。
__init__
内の変数:
これらのinstance variablesの値は、手元のインスタンスにのみアクセス可能です(self
参照を介して)
私の貢献:
static class variablesを使用する際にプログラマが考慮しなければならないことの1つは、instance variables( self
参照を介して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
これが誰かに役立つことを願っています
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
...
...
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.email
、User.firstname
、およびUser.lastname
のそれぞれの値は'none'
ですが、オブジェクト変数u1.email
、u1.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')
クラスとインスタンスの辞書を追跡する場合、これは非常に簡単に理解できます。
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
キー値ペアが含まれることが重要です。
これが特定の変数について知っておくべきことのすべてです。