TypeError:__class__赋值仅支持堆类型或ModuleType子类

Ray*_*emi 3 python setattr

我正在尝试将函数从任意“基”类复制到新对象中。但是,此示例代码出现以下错误。

class my_base:
    def print_hey():
        print("HEY")

    def get_one():
        print(1)

class my_ext:
    def __init__(self, base):
        methods = [method for method in dir(base) if callable(getattr(base, method))]
        for method in methods:
            setattr(self, method, getattr(base, method))


me = my_ext(my_base)
me.get_one()
Run Code Online (Sandbox Code Playgroud)

上面在调用时出现此错误setattr

 TypeError: __class__ assignment only supported for heap types or ModuleType subclasses
Run Code Online (Sandbox Code Playgroud)

如果在定义以上内容后在提示中键入该语句,则该语句有效。

Ara*_*Fey 5

这里的问题是python中的所有对象都有一个__class__存储对象类型的属性:

>>> my_base.__class__
<class 'type'>
>>> type(my_base)
<class 'type'>
Run Code Online (Sandbox Code Playgroud)

由于调用类是您创建该类实例的方式,因此它们被视为可调用对象并通过callable测试:

>>> callable(my_base)
True
>>> my_base()
<__main__.my_base object at 0x7f2ea5304208>
Run Code Online (Sandbox Code Playgroud)

当您的代码尝试向__class__属性分配某些内容时,将抛出您观察到的TypeError:

>>> object().__class__ = int
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: __class__ assignment only supported for heap types or ModuleType subclasses
Run Code Online (Sandbox Code Playgroud)

因此,您需要更具体地确定应复制哪些属性。

您可以使用双下划线过滤掉属性:

methods = [method for method in dir(base) if not method.startswith('__')
                                             and callable(getattr(base, method))]
Run Code Online (Sandbox Code Playgroud)

或者您可以过滤出类:

methods = [method for method in dir(base) if callable(getattr(base, method)) and
                                     not isinstance(getattr(base, method), type)]
Run Code Online (Sandbox Code Playgroud)

或者您只能通过与以下内容进行比较来允许功能types.FunctionType

methods = [method for method in dir(base) if callable(getattr(base, method)) and
                           isinstance(getattr(base, method), types.FunctionType)]
Run Code Online (Sandbox Code Playgroud)