如何重写Python中的__getattribute__()
我想修改一个实例的 __getattribute__()
方法。你可能已经知道,__getattribute__
在 Python 中是一个只读属性(编辑:显然,对于某些对象来说是这样,而对于其他对象则不是)。我想的办法是,像这样创建一个新对象:
def create_new_instace(old_instance):
class temp(old_instance.__class__):
def __init__(self,*args,**kwargs):
"Since we will copy an already inited instance"
pass
def __getattribute__(self,attr):
# do stuff
new_instance = temp()
# magically copy all attrs of old_instance to new_instance
return new_instance
这种事情可能吗?我并没有遇到具体的问题,只是想知道怎么做。
3 个回答
我不太明白你的目标。如果你只是想创建一个和另一个对象一模一样的新对象,你可以使用
from copy import copy
new_instance = copy( old_instance )
这会创建一个“浅拷贝”。如果你需要创建一个“深拷贝”的对象,可以使用 copy.deepcopy
。
如果你想要一个派生类,这个类里有另一个实例的属性(可能还有其他一些你需要动态调整的定制),你可以使用:
from copy import copy
def create_new_instance( old_instance ):
class NewClass( old_instance.__class__ ):
"""
dynamic custom class
"""
# ... customizations
new_instance = copy( old_instance )
new_instance.__class__ = NewClass
不过,这种方法对某些系统类类型是无效的,因为它们的 __class__
不能被赋值。(比如列表、元组、字符串,我想是这样的)。
在这些情况下,你可以用 __new__
来定义你的派生类……但我不太确定有没有“标准”的方法来定义参数——你可能需要逐个情况去处理。
请注意,除非你有其他理由需要动态创建这个新类,否则你不需要在函数内部定义它。
在Python 2.2及以上版本中,你可以这样做。具体的操作方法可以参考这里(搜索getattirbute),看看你需要注意哪些细节:http://www.python.org/download/releases/2.2/descrintro/
其实,是的。你可以查看一下 __getattribute__
和 __getattr__
这两个方法的区别,详细信息可以在这里找到。
你可以给实例的字段 __getattribute__
赋新值,前提是 __setattr__
没有明确禁止这样做。在你的 Python 提示符下试试这个:
>>>class A(object):
>>> pass
>>>A().__getattribute__ = myFunc
>>>A().__getattr__ = myFunc
如果 __setattr__
不允许你这样做,那你就得像你提到的解决方案那样去做。可以查看一下 copy
模块,了解如何“神奇地复制”属性。