因此,如果我在初始化之前尝试使用内置列表进行此类操作:
list.hack = 'impossible'
我收到TypeError。
TypeError: can't set attributes of built-in/extension type 'list'
但是如果我使我的类像这样扩展内置列表:
class mylist(list):
def __setattr__(self, name, value):
raise NotImplementedError
我可以奇怪地做到这一点:
mylist.hack = 'haha'
并且当我初始化“ mylist”时,我将在其中包含“ hack”属性。
x = mylist()
x.hack
[Out]: 'haha'
即使我在初始化“ mylist”之后无法设置任何新属性,也可以在初始化前的状态下进行设置。
自定义类是否有可能获得与内置类相同的预初始化行为?
首先,不需要__setattr__
def:
>>> class MyList(list):
... pass
>>> MyList.hack = 'haha'
>>> x = MyList()
>>> x.hack
'haha'
您不是将属性添加到实例(x
),而是添加到类(MyList
)。 (对于某些语言,这些语言使用static
关键字属性(C ++,Java,PHP等)。)
大致相当于:
>>> class MyList(list):
... hack = 'haha' # class attribute, ie. "static"
>>> x = MyList()
>>> x.hack
'haha'
注意,这与之前/之后的初始化无关:
>>> class MyList(list):
... hack = 'haha'
>>> x = MyList()
>>> MyList.hack2 = 'hehe' # post init
您有:
>>> x.hack
'haha'
而且:
>>> x.hack2
'hehe'
总结,在Python中:
x
是C
的实例,并且attr
是C
的属性,则x.attr
等效于C.attr
。为了记录,您可以使用元类防止这种灵活的行为:
>>> class MyListMeta(type):
... def __setattr__(self, name, value):
... raise AttributeError()
>>> class MyList(list, metaclass=MyListMeta):
... hack = 'haha'
按预期:
>>> x = MyList()
>>> x.hack
'haha'
但是现在:
>>> MyList.hack2 = 'hehe'
Traceback (most recent call last):
...
AttributeError
注意,您也不能设置现有属性:
>>> MyList.hack = 'hehe'
Traceback (most recent call last):
...
AttributeError
备注:
评论摘要:不这样做。