Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

changing the class of a python object (casting)

On this python doc page it says:

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

And I try this script,

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

The result shows:

<class '__main__.Foo'> <class '__main__.Bar'> 1 2

I think I changed the type of f2.
What's wrong, What am I missing?

like image 501
adamsmith Avatar asked Mar 14 '13 08:03

adamsmith


People also ask

How do you change the class of an object in Python?

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

How do you cast an object to a custom class in Python?

The Cast. _to method, is used to cast your custom object, to the desired class. Use the flow control to handle various cases. In this example, if casting to a str class, it will use the json dumps to convert the object to a json string.

Can you edit a class in Python?

You can't edit the class directly like you might with javascript's prototype attribute, it's better if you subclass them.

Can you cast objects in Python?

Python avoids the loss of data in Implicit Type Conversion. Explicit Type Conversion is also called Type Casting, the data types of objects are converted using predefined functions by the user. In Type Casting, loss of data may occur as we enforce the object to a specific data type.


2 Answers

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 
like image 112
HYRY Avatar answered Oct 14 '22 00:10

HYRY


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.

like image 40
Lutz Prechelt Avatar answered Oct 14 '22 01:10

Lutz Prechelt