在Python中定义类变量的正确方法[重复]

Posted

技术标签:

【中文标题】在Python中定义类变量的正确方法[重复]【英文标题】:correct way to define class variables in Python [duplicate] 【发布时间】:2012-02-21 20:08:09 【问题描述】:

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

第一种方式是这样的:

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

  def __init__(self):
    #pass or something else

另一种风格是这样的:

class MyClass:
  def __init__(self):
    self.__element1 = 123
    self.__element2 = "this is Africa"

初始化类属性的正确方法是什么?

【问题讨论】:

如果你使用字符串,差异并不大......但如果你使用通过引用存储的字典或列表,它会得到完全不同的东西 【参考方案1】:

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

__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

如您所见,当我们更改类元素时,这两个对象都发生了变化。但是,当我们更改对象元素时,另一个对象保持不变。

【讨论】:

但是init总是在对象被创建之后执行,它实际上等于在init之外定义变量,对吧? 如果你改变了一个类属性(一个在__init__()之外定义的)它会改变整个类。对于其他实例,它也会发生变化,而实例属性(在__init__() 中定义)特定于每个实例。 不完全准确:当通过类 (MyClass.static_element = X) 分配给所有类实例时,static_elm 会发生变化,如图所示。但是当通过类实例分配时,对于该实例static_elm 将成为实例成员。如果你这样做:c1.static_elem = 666,那么print c1.static_elem, c2.static_elem 将产生666, 999。在班级内,self.static_elm 返回MyClass.static_elm 直到分配 self.static_elm = X。然后,一个新的 self.static_elm 被创建,隐藏类变量(仍然可以通过MyClass.static_elm 访问) Lobotomik 做了明确的解释。是的,在 Python 上这是一个奇怪的设计,在 Python 中设计的这个特性很容易混淆,因为类元素可能会突然变成实例的元素。 @Lobotomik:我相信它只是“隐藏”类变量,因为您仍然可以通过 c1.__class__.static_elem 访问未修改的类变量。我理解您的话“static_elm 将成为实例成员”,因为 static_elem 将从类变量变为实例变量。事实并非如此。【参考方案2】:

我认为这个示例解释了样式之间的区别:

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'

element1 绑定到类,element2 绑定到类的一个实例。

【讨论】:

我无法编辑或建议编辑。 obj.element1obj.element2 的输出搞砸了。

以上是关于在Python中定义类变量的正确方法[重复]的主要内容,如果未能解决你的问题,请参考以下文章

使用类自变量作为默认类方法参数[重复]

python在定义类的时候,如何把类函数传递给另一个变量,如下

Python - 如何按定义的顺序将类变量存储到数组中[重复]

如何从类变量中调用函数方法[重复]

python面向对象中类对象实例对象类变量实例变量类方法实例方法静态方法

如何在其他方法中访问类属性变量[重复]