我一直在使用namedlist来创建轻量级类:
from namedlist import namedlist
# create a class
SomeClass = namedlist('SomeClass', 'foo bar', use_slots=False)
# create an object
my_list = SomeClass(1,2)
# set an attribute not specified in the class
my_list.baz = 3
# the attribute is there if I reference it
print(my_list.baz)
# output: 3
有时我想拍摄一个对象,看看是否设置了任何额外的属性:
# this doesn't show 'baz'
import inspect
inspect.getmembers(my_list)
# neither does this
my_list.__dict__
有没有办法可以看到以这种方式添加的任何属性?
答案 0 :(得分:1)
查看namedlist
的来源,我们可以看到工厂函数namedlist()
生成类型(示例中为SomeClass
)。
现在这很有趣。
一方面,__getattribute__
和__setattribute__
没有重载,这使您可以执行my_list.baz = 3
之类的操作,然后将其作为my_list.baz
进行访问。
另一方面,__dict__
被property(_asdict)
覆盖(在_common_fields()
中生成)。这会导致使用__dict__
的用户无法看到baz
- dir()
和inspect
模块等功能。
虽然在这种情况下我找不到列出添加属性的函数,但如果您知道要查找的属性,仍然可以使用hasattr(my_list, 'baz')
检查它是否存在:
>>> from namedlist import namedlist
>>> SomeClass = namedlist('SomeClass', 'foo bar', use_slots=False)
>>> my_list = SomeClass(1,2)
>>> my_list.baz = 3
>>> hasattr(my_list, 'baz')
True
答案 1 :(得分:0)
如果切换类型有问题(可能已经使用了命名列表的旧代码),我发现以下内容使得查看namedlist
可以忍受:
def set_attr(self, attr_name, attr_val):
setattr(self, attr_name, attr_val)
self.opt_attrs.append(attr_name)
TypeA = namedlist('TypeA', 'field_a opt_attrs', use_slots=False)
TypeA.set_attr = set_attr
TypeB = namedlist('TypeB', 'field_b opt_attrs', use_slots=False)
TypeB.set_attr = set_attr
objA = TypeA(1, [])
objA.set_attr('field_x', 2)
objB = TypeB(7, [])
objA
# Out: TypeA(field_a=1, opt_attrs=['field_x'])
objA.field_x
# Out: 2
objB
# Out: TypeB(field_b=7, opt_attrs=[])
最好只使用python类。更多的前期代码,更少的事后混淆:
class TypeA:
def __init__(self, a):
self.a = a
def __repr__(self):
return "A(a={})".format(self.a)
class TypeB:
def __init__(self, b):
self.b = b
def __repr__(self):
return "B(b={})".format(self.b)
A = TypeA(1)
A.x = 2
B = TypeB(7)
class TypeA:
def __init__(self, a):
self.a = a
def __repr__(self):
return "A(a={})".format(self.a)
class TypeB:
def __init__(self, b):
self.b = b
def __repr__(self):
return "B(b={})".format(self.b)
objA = TypeA(1)
objA.x = 2
objB = TypeB(7)
objA
# Out: A(a=1)
objA.__dict__
# Out: {'a': 1, 'x': 2}
objB
# Out: B(b=7)