两种类属性定义的区别?

时间:2012-02-16 09:32:47

标签: python class

之间有区别吗?
class Foo(object):
    bar = 1
    def __init__(self):
        ... etc.

class Foo(object):
    def __init__(self):
       ... etc.

Foo.bar = 1

在这两种情况下bar都是类的属性,对于类的所有实例都是一样的,对吗?

3 个答案:

答案 0 :(得分:4)

我要说的唯一区别是,在第二种情况下,Foo.bar在执行Foo.bar = 1语句之前不存在,而在第一种情况下,当类对象是创建

这可能是一个小的差异而对你的代码没有任何影响(除非在第二种情况下有一些代码需要Foo.bar才可用)。但是,我会说第一个选项在可读性方面更好,因为你不必向下滚动来了解你的类的属性,它们已经存在。

答案 1 :(得分:4)

如果您正在编写自己的代码,请使用:

class Foo(object):
    bar = 1

知道这个版本:

class Foo(object):
    pass

Foo.bar = 1

即使它是合法的

  1. 看起来更像是一个黑客。
  2. 在大多数情况下可读性较差。
  3. 如果您在创建bar属性之前尝试访问该属性,则可能会遇到问题:

    >>> class Foo:
    ...     pass
    ... 
    >>> f = Foo()
    >>> f.bar
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    AttributeError: 'Foo' object has no attribute 'bar'
    >>> Foo.bar = 1
    >>> f.bar   # but hey, now you're ok!
    1
    
  4. 除此之外,我没有看到很多差异。

答案 2 :(得分:-1)

两个版本都是相同的(请参阅本答案末尾的测试记录),但请注意,({)在bar的所有实例中,Foo都不是bar

在创建实例时,在实例上阅读Foo将读取Foo.bar中的值,instance.bar的分配将反映在实例中,直到{ {1}}已分配给。在分配的那一刻,实例获得自己的__dict__条目,该条目完全独立于类。

In [62]: class Foo: pass

In [63]: Foo.bar = 1

In [64]: Foo.bar
Out[64]: 1

In [65]: f = Foo()

In [66]: f.bar
Out[66]: 1

In [67]: f.bar +=1

In [68]: f.bar
Out[68]: 2

In [69]: Foo.bar
Out[69]: 1

In [70]: Foo.bar +=3

In [71]: Foo.bar
Out[71]: 4

In [72]: g = Foo()

In [73]: g.bar
Out[73]: 4

In [74]: class Qux: bar = 1

In [75]: Qux.bar
Out[75]: 1

In [76]: q = Qux()

In [77]: q.bar
Out[77]: 1

In [78]: q.bar+=1

In [79]: q.bar
Out[79]: 2

In [80]: Qux.bar
Out[80]: 1

In [81]: Qux.bar +=1

In [82]: r = Qux()

In [83]: r.bar
Out[83]: 2

In [84]: q.bar
Out[84]: 2

In [85]: s = Qux()

In [87]: s.__dict__
Out[87]: {}

In [88]: q.__dict__
Out[88]: {'bar': 2}

In [89]: Qux.bar = 'foo'

In [90]: Qux.bar
Out[90]: 'foo'

In [91]: s.bar
Out[91]: 'foo'