目前 __ setattr __ 仅适用于实例。上课有类似的方法吗?我问这个问题是因为当用户在课堂上定义时,我想按顺序收集已定义属性的列表:
class CfgObj(object):
_fields = []
def __setattr__(self, name, value):
self._fields.append([name, value])
object.__setattr__(self, name, value)
class ACfg(CfgObj):
setting1 = Field(str, default='set1', desc='setting1 ...')
setting2 = Field(int, default=5, desc='setting2...')
我知道上面的代码无法按预期工作,因为 __ setattr __ 仅按实例调用如下:
acfg = ACfg()
acfg.c = 1
acfg._fields == [['c', 1]]
那么,python类有没有等效的 __ setattr __ ?主要目的是在用户在类中定义时按顺序收集define属性。
答案 0 :(得分:3)
是的,但是that's not how you want to do it。
class MC(type):
def __init__(cls, name, bases, dct):
print dct
super(MC, cls).__init__(name, bases, dct)
class C(object):
__metaclass__ = MC
foo = 42
答案 1 :(得分:3)
如果在类的元类上定义__setattr__()
,则在类上设置属性时会调用它,但仅在创建类后才会调用:
>>> class Meta(type):
... def __setattr__(cls, name, value):
... print "%s=%r" % (name, value)
...
>>> class A(object):
... __metaclass__ = Meta
...
>>> A.a = 1
a=1
但是在课程定义时它不起作用,所以它可能不是你想要的。
获取元类__init__()
中的类属性有效,但是你失去了定义的顺序(以及多个定义)。
答案 2 :(得分:0)
我将如何解决您的问题 - 而不是您的问题 - 是设置字段创建的时间戳创建一个计数器Field
个对象,并将计数器的当前值设置为创建的对象:
class Field(object):
count = 0
def __init__(self, value, default=None, desc=None):
self.value = value
self.default = default
self.desc = desc
# Here comes the magic
self.nth = Field.count
Field.count += 1
# self.created_at = time.time()
然后我会创建一个方法来返回按其计数器值排序的所有字段:
class CfgObj(object):
def params(self):
ns = dir(self)
fs = [getattr(self, field)
for field in ns
if isinstance(getattr(self, field), Field)]
# fs = sorted(fs, key=lambda f: f.created_at)
fs = sorted(fs, key=lambda f: f.nth)
return fs
它的用法很直观:
class ACfg(CfgObj):
setting1 = Field(str, default='set1', desc='setting1 ...')
setting2 = Field(int, default=5, desc='setting2...')
print ACfg().params()
显然,字段按对象创建时间排序,而不是 field 创建,但对您来说已经足够了。是吗?