如何重写Python中的__getattribute__()

0 投票
3 回答
1099 浏览
提问于 2025-04-17 02:29

我想修改一个实例的 __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 个回答

0

我不太明白你的目标。如果你只是想创建一个和另一个对象一模一样的新对象,你可以使用

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__ 来定义你的派生类……但我不太确定有没有“标准”的方法来定义参数——你可能需要逐个情况去处理。

请注意,除非你有其他理由需要动态创建这个新类,否则你不需要在函数内部定义它。

0

在Python 2.2及以上版本中,你可以这样做。具体的操作方法可以参考这里(搜索getattirbute),看看你需要注意哪些细节:http://www.python.org/download/releases/2.2/descrintro/

2

其实,是的。你可以查看一下 __getattribute____getattr__ 这两个方法的区别,详细信息可以在这里找到。

你可以给实例的字段 __getattribute__ 赋新值,前提是 __setattr__ 没有明确禁止这样做。在你的 Python 提示符下试试这个:

>>>class A(object):
>>>    pass
>>>A().__getattribute__ = myFunc
>>>A().__getattr__ = myFunc

如果 __setattr__ 不允许你这样做,那你就得像你提到的解决方案那样去做。可以查看一下 copy 模块,了解如何“神奇地复制”属性。

撰写回答