Python 类与模块属性
问题描述
我有兴趣听到一些关于 Python 中的类属性的讨论.例如,什么是类属性的好用例?在大多数情况下,我想不出一个类属性比使用模块级属性更可取的情况.如果这是真的,那为什么还有他们呢?
I'm interested in hearing some discussion about class attributes in Python. For example, what is a good use case for class attributes? For the most part, I can not come up with a case where a class attribute is preferable to using a module level attribute. If this is true, then why have them around?
我遇到的问题是,错误地破坏类属性值几乎太容易了,然后你的全局"值变成了本地实例属性.
The problem I have with them, is that it is almost too easy to clobber a class attribute value by mistake, and then your "global" value has turned into a local instance attribute.
请随意评论您将如何处理以下情况:
Feel free to comment on how you would handle the following situations:
- 类和/或子类使用的常量值.这可能包括永远不会改变但可能需要一次性初始化的幻数"字典键或列表索引.
- 默认类属性,在极少数情况下为类的特殊实例更新.
- 用于表示在所有实例之间共享的类的内部状态的全局数据结构.
- 初始化许多默认属性的类,不受构造函数参数的影响.
一些相关帖子:
类和实例属性的区别
解决方案
#4:我从不使用类属性来初始化默认实例属性(通常放在 __init__
中的那些).例如:
#4:
I never use class attributes to initialize default instance attributes (the ones you normally put in __init__
). For example:
class Obj(object):
def __init__(self):
self.users = 0
永远不会:
class Obj(object):
users = 0
为什么?因为它是不一致的:当您分配除不变对象之外的任何东西时,它不会做您想做的事情:
Why? Because it's inconsistent: it doesn't do what you want when you assign anything but an invariant object:
class Obj(object):
users = []
使用户列表在所有对象之间共享,在这种情况下,这是不希望的.根据它们的类型将它们拆分为 __init__
中的类属性和赋值会令人困惑,因此我总是将它们全部放在 __init__
中,反正我觉得这样更清楚.
causes the users list to be shared across all objects, which in this case isn't wanted. It's confusing to split these into class attributes and assignments in __init__
depending on their type, so I always put them all in __init__
, which I find clearer anyway.
至于其余部分,我通常将特定于类的值放在类中.这并不是因为全局变量是邪恶的"——它们不像在某些语言中那么重要,因为它们仍然局限于模块,除非模块本身太大——但是如果外部代码想要访问它们,将所有相关值放在一个地方很方便.比如在module.py中:
As for the rest, I generally put class-specific values inside the class. This isn't so much because globals are "evil"--they're not so big a deal as in some languages, because they're still scoped to the module, unless the module itself is too big--but if external code wants to access them, it's handy to have all of the relevant values in one place. For example, in module.py:
class Obj(object):
class Exception(Exception): pass
...
然后:
from module import Obj
try:
o = Obj()
o.go()
except o.Exception:
print "error"
除了允许子类更改值(这并不总是需要)之外,这意味着我不必费力地导入异常名称和使用 Obj 所需的一堆其他东西."from module import Obj, ObjException, ..." 很快就会让人厌烦.
Aside from allowing subclasses to change the value (which isn't always wanted anyway), it means I don't have to laboriously import exception names and a bunch of other stuff needed to use Obj. "from module import Obj, ObjException, ..." gets tiresome quickly.
相关文章