changing the class of a python object (casting)

后端 未结 4 1625
滥情空心
滥情空心 2020-12-01 13:44

On this python doc page it says:

Like its identity, an object’s type is also unchangeable.

And I try this script,

<         


        
相关标签:
4条回答
  • 2020-12-01 14:29

    I was asked this question by a colleague today. He had a parent class that wanted to promote itself automatically to be one of its children based on an input at init time. The following script worked as a proof of concept:

    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'))
    

    The result shows:

    <class '__main__.ClassA'>
    you gave me sausage
    Thankyou
    I give you cabbage
    You are welcome
    

    Which shows that both the parent and child functions are now available to A.

    0 讨论(0)
  • 2020-12-01 14:33

    Old question but here's a technique for safely extending the type of a python object.

    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
    
    0 讨论(0)
  • 2020-12-01 14:34

    The footnotes one that page says:

    [1] It is possible in some cases to change an object’s type, under certain controlled conditions. It generally isn’t a good idea though, since it can lead to some very strange behaviour if it is handled incorrectly.

    If you try to change the __class__ of f2 to list:

    f2.__class__ = list
    

    A TypeError raised:

    TypeError: __class__ assignment: only for heap types
    
    0 讨论(0)
  • 2020-12-01 14:46

    When and how to do this

    Changing the type ("casting") makes sense if you want to add functionality to an object created by some code you cannot change.

    Assume some statement obj = some_call_to_a_library() gives you an object of class A. You want it to have additional functionality, say, mymethod(). Then you could introduce a subclass MyA like this (Python 3 style):

    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):
            ...
    

    and then write obj = MyA.cast(some_call_to_a_library()). If MyA relies on additional attributes, cast (which is a factory method) should create them.

    I just did something like this when I needed a version of requests.Response that could persist and retrieve responses to/from a file.

    0 讨论(0)
提交回复
热议问题