在python doc page上,它说:
与其身份一样,对象的类型也是不可更改的。
我试试这个剧本,
#!python3
class Foo:
num = 1
pass
class Bar:
num = 2
pass
f1,f2= Foo(), Foo()
f2.__class__ = Bar
print( type(f1), type(f2), f1.num, f2.num )
结果显示:
<class '__main__.Foo'> <class '__main__.Bar'> 1 2
我想我改变了type
的{{1}}
怎么了,我错过了什么?
答案 0 :(得分:14)
页面上的脚注:
[1]在某些情况下,可以更改对象的类型 某些受控条件。但这通常不是一个好主意, 因为如果处理它会导致一些非常奇怪的行为 不正确。
如果您尝试将f2的__class__
更改为list
:
f2.__class__ = list
引发了一个TypeError:
TypeError: __class__ assignment: only for heap types
答案 1 :(得分:4)
更改类型(&#34;强制转换&#34;)是有意义的,如果您想要添加功能到由您无法更改的某些代码创建的对象。
假设某些语句obj = some_call_to_a_library()
为您提供了类A
的对象。您希望它具有其他功能,例如mymethod()
。
然后你可以像这样引入一个子类MyA
(Python 3风格):
class MyA(A):
@classmethod
def cast(cls, some_a: A):
"""Cast an A into a MyA."""
assert isinstance(some_a, A)
some_a.__class__ = cls # now mymethod() is available
assert isinstance(some_a, MyA)
return some_a
def mymethod(self):
...
然后写obj = MyA.cast(some_call_to_a_library())
。
如果MyA
依赖于其他属性,则cast
(这是一种工厂方法)应该创建它们。
当我需要一个requests.Response
版本可以持久存储并从文件中检索响应时,我就做了类似的事情。
答案 2 :(得分:1)
今天有人问我这个问题。他有一个父类,希望在初始时根据输入自动提升自己成为其中一个孩子。以下脚本用作概念证明:
class ClassB(object):
def __init__(self):
self.__class__ = ClassA
def blah2(self,t):
print('I give you',t)
return 'You are welcome'
class ClassA(ClassB):
def blah(self, t):
print('you gave me',t)
return 'Thankyou'
a = ClassB()
print(type(a))
print(a.blah('sausage'))
print(a.blah2('cabbage'))
结果显示:
<class '__main__.ClassA'>
you gave me sausage
Thankyou
I give you cabbage
You are welcome
这表明父和子函数现在都可用于A
。
答案 3 :(得分:0)
古老的问题,但这是一种安全地扩展python对象类型的技术。
def extendObject(obj):
# Our extended type is explicitly derived from our existing type.
class Extended(obj.__class__):
# Whatever extensions you want to make.
def someMethod(self):
pass
# Change the type of the object.
obj.__class__ = Extended
return obj