Say I have a class, which has a number of subclasses.
I can instantiate the class. I can then set its __class__
attribute to one of the subclasses. I have effectively changed the class type to the type of its subclass, on a live object. I can call methods on it which invoke the subclass's version of those methods.
So, how dangerous is doing this? It seems weird, but is it wrong to do such a thing? Despite the ability to change type at run-time, is this a feature of the language that should completely be avoided? Why or why not?
(Depending on responses, I'll post a more-specific question about what I would like to do, and if there are better alternatives).
self. __class__ is a reference to the type of the current instance. Throwing an exception here is like using an assert statement elsewhere in your code, it protects you from making silly mistakes. type() should be preferred over self.
self represents the instance of the class. By using the “self” we can access the attributes and methods of the class in python. It binds the attributes with the given arguments. The reason you need to use self. is because Python does not use the @ syntax to refer to instance attributes.
Class methods don't need a class instance. They can't access the instance ( self ) but they have access to the class itself via cls . Static methods don't have access to cls or self . They work like regular functions but belong to the class's namespace.
The self keyword is used to represent an instance (object) of the given class. In this case, the two Cat objects cat1 and cat2 have their own name and age attributes. If there was no self argument, the same class couldn't hold the information for both these objects.
Here's a list of things I can think of that make this dangerous, in rough order from worst to least bad:
__init__
method, so you probably won't have all of the instance variables initialized properly (or even at all).__slots__
, all of the classes must have identical slots. (And if you have the compatible but different slots, it may appear to work at first but do horrible things…) __new__
, things will not work the way you naively expected.Meanwhile, in many cases where you'd think this is necessary, there are better options:
__new__
or other mechanisms to hook the construction.As a very most common specific case of the last one, just put all of the "variable methods" into classes whose instances are kept as a data member of the "parent", rather than into subclasses. Instead of changing self.__class__ = OtherSubclass
, just do self.member = OtherSubclass(self)
. If you really need methods to magically change, automatic forwarding (e.g., via __getattr__
) is a much more common and pythonic idiom than changing classes on the fly.
Assigning the __class__
attribute is useful if you have a long time running application and you need to replace an old version of some object by a newer version of the same class without loss of data, e.g. after some reload(mymodule)
and without reload of unchanged modules. Other example is if you implement persistency - something similar to pickle.load
.
All other usage is discouraged, especially if you can write the complete code before starting the application.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With