在Python中定义类变量的正确方法

jea*_*anc 231 python attributes class

可能重复:
类__init __()函数内部和外部的变量

我注意到在Python中,人们以两种不同的方式初始化他们的类属性.

第一种方式是这样的:

class MyClass:
  __element1 = 123
  __element2 = "this is Africa"

  def __init__(self):
    #pass or something else
Run Code Online (Sandbox Code Playgroud)

另一种风格如下:

class MyClass:
  def __init__(self):
    self.__element1 = 123
    self.__element2 = "this is Africa"
Run Code Online (Sandbox Code Playgroud)

哪个是初始化类属性的正确方法?

jul*_*ria 521

这两种方式都不一定正确或不正确,它们只是两种不同的类元素:

  • __init__方法之外的元素是静态元素; 他们属于这个班级.
  • 内部元件__init__方法是对象的元件(self); 他们不属于班级.

您可以通过一些代码更清楚地看到它:

class MyClass:
    static_elem = 123

    def __init__(self):
        self.object_elem = 456

c1 = MyClass()
c2 = MyClass()

# Initial values of both elements
>>> print c1.static_elem, c1.object_elem 
123 456
>>> print c2.static_elem, c2.object_elem
123 456

# Nothing new so far ...

# Let's try changing the static element
MyClass.static_elem = 999

>>> print c1.static_elem, c1.object_elem
999 456
>>> print c2.static_elem, c2.object_elem
999 456

# Now, let's try changing the object element
c1.object_elem = 888

>>> print c1.static_elem, c1.object_elem
999 888
>>> print c2.static_elem, c2.object_elem
999 456
Run Code Online (Sandbox Code Playgroud)

如您所见,当我们更改了class元素时,它对两个对象都进行了更改.但是,当我们更改了对象元素时,另一个对象保持不变.

  • 不完全准确:`static_elm`在通过类(`MyClass.static_element = X`)分配给所有类实例时会发生变化,如图所示.但是,当通过类实例分配时,_for_ instance_,`static_elm`将成为实例成员.如果你这样做:`c1.static_elem = 666`,那么`print c1.static_elem,c2.static_elem`将产生`666,999`.在类中,`self.static_elm`返回`MyClass.static_elm` _until assigned_`self.static_elm = X`.然后,创建_a new_`self.static_elm`,隐藏类变量(仍可通过`MyClass.static_elm`访问) (34认同)
  • 我完全了解你的例子,非常感谢你 (10认同)
  • @Lobotomik:我相信它只是“隐藏”类变量,因为您仍然可以通过 c1.__class__.static_elem 访问未修改的类变量。我理解您的话“static_elm 将成为实例成员”,因为 static_elem 将从类变量变为实例变量。不是这种情况。 (3认同)
  • 但是在创建对象后总是执行__init__,它实际上等于定义__init__之外的变量,对吧? (2认同)
  • 如果更改了一个类属性(一个在`__init __()`之外定义的属性),它将改变整个类.它也将为其他实例更改,而实例属性(在`__init __()`中定义)特定于每个实例. (2认同)
  • Lobotomik做出了明确的解释。是的,在Python上这是一个奇怪的设计,很容易混淆在Python上设计的此功能,因为class元素可能会突然更改为实例的元素。 (2认同)

Jam*_*ley 15

我想这个样本解释了样式之间的区别:

james@bodacious-wired:~$cat test.py 
#!/usr/bin/env python

class MyClass:
    element1 = "Hello"

    def __init__(self):
        self.element2 = "World"

obj = MyClass()

print dir(MyClass)
print "--"
print dir(obj)
print "--"
print obj.element1 
print obj.element2
print MyClass.element1 + " " + MyClass.element2
james@bodacious-wired:~$./test.py 
['__doc__', '__init__', '__module__', 'element1']
--
['__doc__', '__init__', '__module__', 'element1', 'element2']
--
Hello World
Hello
Traceback (most recent call last):
  File "./test.py", line 17, in <module>
    print MyClass.element2
AttributeError: class MyClass has no attribute 'element2'
Run Code Online (Sandbox Code Playgroud)

element1绑定到类,element2绑定到类的实例.