Python类与模块属性

cmc*_*nty 13 python attributes class-design module

我有兴趣听一些关于Python中类属性的讨论.例如,类属性的一个很好的用例是什么?在大多数情况下,我无法想出一个类属性比使用模块级属性更可取的情况.如果这是真的,那么为什么要将它们放在一边?

我遇到的问题是,错误地破坏类属性值几乎太容易了,然后你的"全局"值变成了本地实例属性.

请随意评论您将如何处理以下情况:

  1. 类和/或子类使用的常量值.这可能包括永不改变的"幻数"字典键或列表索引,但可能需要一次性初始化.
  2. 默认类属性,在极少数情况下为类的特殊实例更新.
  3. 全局数据结构用于表示在所有实例之间共享的类的内部状态.
  4. 初始化许多默认属性的类,不受构造函数参数的影响.

一些相关帖子:
类和实例属性之间的差异

Gle*_*ard 7

#4:我从不使用类属性来初始化默认实例属性(通常放入的属性__init__).例如:

class Obj(object):
    def __init__(self):
        self.users = 0
Run Code Online (Sandbox Code Playgroud)

永不:

class Obj(object):
    users = 0
Run Code Online (Sandbox Code Playgroud)

为什么?因为它不一致:当你分配除了一个不变对象之外的东西时,它不会做你想要的东西:

class Obj(object):
    users = []
Run Code Online (Sandbox Code Playgroud)

导致用户列表在所有对象之间共享,在这种情况下不需要.__init__根据它们的类型将它们分成类属性和赋值是令人困惑的,所以我总是把它们全部放进去__init__,无论如何我都觉得更清楚了.


至于其余部分,我通常会在类中放置特定于类的值.这不是因为全局变量是"邪恶的" - 它们并不像某些语言那么大,因为它们仍然是模块化的,除非模块本身太大 - 但是如果是外部代码想要访问它们,将所有相关值放在一个地方很方便.例如,在module.py中:

class Obj(object):
    class Exception(Exception): pass
    ...
Run Code Online (Sandbox Code Playgroud)

然后:

from module import Obj

try:
    o = Obj()
    o.go()
except o.Exception:
    print "error"
Run Code Online (Sandbox Code Playgroud)

除了允许子类更改值(无论如何总是不需要),这意味着我不必费力地导入异常名称和使用Obj所需的一堆其他东西."从模块导入Obj,ObjException,......"很快就变得很烦人.