30

在这个python 文档页面上它说:

像它的身份一样,对象的类型也是不可更改的。

我试试这个脚本,

#!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

我想我改变typef2.
怎么了,我错过了什么?

4

4 回答 4

20

该页的脚注说:

[1] 在某些受控条件下,在某些情况下可以更改对象的类型。不过,这通常不是一个好主意,因为如果处理不当,可能会导致一些非常奇怪的行为。

如果您尝试将__class__f2 更改为list

f2.__class__ = list

引发 TypeError:

TypeError: __class__ assignment: only for heap types
于 2013-03-14T08:41:43.360 回答
15

何时以及如何执行此操作

如果您想向由某些无法更改的代码创建的对象添加功能,则更改类型(“强制转换”)是有意义的。

假设某些语句obj = some_call_to_a_library()为您提供了 class 的对象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当我需要一个可以持续存在并从文件中检索响应的版本时,我只是做了类似的事情。

于 2018-04-12T11:56:12.030 回答
3

今天有个同事问我这个问题。他有一个父类,希望根据初始化时的输入自动将自己提升为它的子类之一。以下脚本用作概念证明:

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.

于 2017-12-01T17:31:13.437 回答
3

老问题,但这是一种安全扩展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
于 2019-03-08T09:39:25.650 回答