Python中初始化属性或属性的最佳实践是什么?

4
Python支持类属性、实例属性和属性。
from time import ctime, sleep

class MyClass(object):
    A = ctime()            # class attribute
    def __init__(self):
        self.B = ctime()   # instance attribute
        self._C = None

    @property
    def C(self):           # property
        if self._C is None:
            self._C = ctime()
        return self._C
    @C.setter
    def C(self, c):
        self._C

对于不了解MyClass实现方式的用户,A、B和C表现出相似的行为:

sleep(2)
myObject = MyClass()
sleep(2)
print myObject.A         # prints time module was initialized
print myObject.B         # prints time instance was created, 2 sec later
print myObject.C         # prints time this line was called, 2 sec later
myObject.A = 'foo'       # myObject.A is now an instance attribute
myObject.B = 'foo'       # myObject.B is still an instance attribute
myObject.C = 'foo'       # myObject.C is still an (instance) property
print myObject.A         # prints 'foo'
print myObject.B         # prints 'foo'
print myObject.C         # prints 'foo'

从我在这里得到的答案,我理解以下内容:第一次打印myObject.A时,myObject.AmyObject.__Class__.A,即MyClass.A。第二次myObject.A不是myObject.__Class__.A。好的。

在上面的示例中,ctime()仅用于说明A、B和C的区别。现在假设我们使用一个不可变常量:

class MyClass(object):
    A = 'bar'               # class attribute
    def __init__(self):
        self.B = 'meta'     # instance attribute
        self._C = None

    @property
    def C(self):            # property
        if self._C is None:
            self._C = 'foobar'
        return self._C
    @C.setter
    def C(self, c):
        self._C = c

myObject = MyClass()

myObject.A 仍然是类属性 MyClass.A,而 myObject.B 是实例属性,myObject.C 是一个属性。它们都能够完美地满足我的需求。它们有默认值,我也可以为它们赋其他的值。那么我应该使用哪种样式,A、B 或 C?


2
实际上,它们并不都“起作用”。它们并不都做相同的事情。foo.A实际上创建了一个实例变量,在现有的Foo.A类变量之前找到。 “我应该使用哪种风格”完全取决于您的目标是什么。您想要实例变量还是类变量?请在问题中包含您的目标。 - S.Lott
3个回答

2

初始化一个常量类属性的首选方式是在类定义本身中完成。

从问题的代码来看,似乎存在一些关于如何从实例对象访问类属性的混淆。

请注意,在实例对象中,您可以通过名称访问类属性,因为当在内部字典中找不到属性时,查找将继续在类字典中进行。也就是说,如果instance.A不存在,则会返回instance.__class__.A(如果可用)。

但是,当在对象实例中创建属性时,该类属性将被隐藏。也就是说,instance.A = <value>创建一个新的实例属性,下一次访问instance.A时,将返回<value>。但仍然可以使用instance.__class__.A检索类属性。


1

这取决于您希望初始化何时运行以及您想要什么实例化。

  • 如果您希望属性的单个实例(即单个值)在类的所有实例之间共享,请使用类属性。
  • 如果您希望类的每个实例都具有属性的不同值,请使用实例属性。

顺便说一下,您的代码示例包含属性而不是属性。

我无法理解您对问题的更新。您可能需要退后一步并解释您的根本问题。


1
似乎有两种创建简单属性或属性的样式。
它们根本不是“样式”,只做了一件事:赋值。
它们具有不同的效果。
在Python中,遵循逻辑规则,即在class块内声明的东西属于该类。因此,A是类的属性(与C++或Java或C#中声明为static的属性大致相当)。B是每个实例的属性,在实例上运行__init__时自动生成。
至于您的更新,我不知道您想要问什么。尝试使用真实名称而非“A”并解释您的用例(即为什么您要执行任何操作)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接