我正在尝试将函数从任意“基”类复制到新对象中。但是,此示例代码出现以下错误。
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)
如果在定义以上内容后在提示中键入该语句,则该语句有效。
这里的问题是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)