TypeError: __class__ assignment only supported for heap types or ModuleType subclasses
TypeError: __class__ assignment only supported for heap types or ModuleType subclasses
我正在尝试将函数从任意 'base' class 复制到我的新对象中。但是,此示例代码出现以下错误。
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()
以上调用 setattr
.
时出现此错误
TypeError: __class__ assignment only supported for heap types or ModuleType subclasses
如果我在定义上面的内容后在提示符中键入该语句,该语句就有效。
您的实例对象有许多不应重新分配的属性,其中大部分都通过了 callable
测试:
>>> [item for item in dir(my_base) if callable(getattr(my_base, item))]
['__class__', '__delattr__', '__dir__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'get_one', 'print_hey']
你应该限制其中的大部分。您可以简单地检查 item.startswith('__')
,但我不确定您想对 __repr__
和朋友做什么。也许在白名单后检查下划线?
事实证明 __class__
是可调用的,并且还有许多其他可调用的。
我只想要功能,所以下面的工作:
import types
. . .
methods = [method for method in dir(base) if isinstance(getattr(base, method), types.FunctionType)]
. . .
这里的问题是 python 中的所有对象都有一个存储对象类型的 __class__
属性:
>>> my_base.__class__
<class 'type'>
>>> type(my_base)
<class 'type'>
由于调用 class 是创建 class 实例的方式,因此它们被视为可调用对象并通过了 callable
测试:
>>> callable(my_base)
True
>>> my_base()
<__main__.my_base object at 0x7f2ea5304208>
并且当您的代码尝试将某些内容分配给 __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
因此您需要更具体地说明应复制哪些属性。
您可以过滤掉带有双下划线的属性:
methods = [method for method in dir(base) if not method.startswith('__')
and callable(getattr(base, method))]
或者您可以过滤掉 classes:
methods = [method for method in dir(base) if callable(getattr(base, method)) and
not isinstance(getattr(base, method), type)]
或者您只能通过比较 types.FunctionType
:
来允许函数
methods = [method for method in dir(base) if callable(getattr(base, method)) and
isinstance(getattr(base, method), types.FunctionType)]
我正在尝试将函数从任意 'base' class 复制到我的新对象中。但是,此示例代码出现以下错误。
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()
以上调用 setattr
.
TypeError: __class__ assignment only supported for heap types or ModuleType subclasses
如果我在定义上面的内容后在提示符中键入该语句,该语句就有效。
您的实例对象有许多不应重新分配的属性,其中大部分都通过了 callable
测试:
>>> [item for item in dir(my_base) if callable(getattr(my_base, item))]
['__class__', '__delattr__', '__dir__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'get_one', 'print_hey']
你应该限制其中的大部分。您可以简单地检查 item.startswith('__')
,但我不确定您想对 __repr__
和朋友做什么。也许在白名单后检查下划线?
事实证明 __class__
是可调用的,并且还有许多其他可调用的。
我只想要功能,所以下面的工作:
import types
. . .
methods = [method for method in dir(base) if isinstance(getattr(base, method), types.FunctionType)]
. . .
这里的问题是 python 中的所有对象都有一个存储对象类型的 __class__
属性:
>>> my_base.__class__
<class 'type'>
>>> type(my_base)
<class 'type'>
由于调用 class 是创建 class 实例的方式,因此它们被视为可调用对象并通过了 callable
测试:
>>> callable(my_base)
True
>>> my_base()
<__main__.my_base object at 0x7f2ea5304208>
并且当您的代码尝试将某些内容分配给 __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
因此您需要更具体地说明应复制哪些属性。
您可以过滤掉带有双下划线的属性:
methods = [method for method in dir(base) if not method.startswith('__')
and callable(getattr(base, method))]
或者您可以过滤掉 classes:
methods = [method for method in dir(base) if callable(getattr(base, method)) and
not isinstance(getattr(base, method), type)]
或者您只能通过比较 types.FunctionType
:
methods = [method for method in dir(base) if callable(getattr(base, method)) and
isinstance(getattr(base, method), types.FunctionType)]