3

is there any possible to override class, or undeclare class or redeclare a Class in python?

2 Answers2

5

Yes, just declare it again:

class Foo(object): x = 1

class Foo(object): x = 2

The above code will not raise any error, and the name Foo will refer to the second class declared. Note however, that the class declared by the first declaration will still exist if anything refers to it, e.g. an instance, or a derived class.

This means that existing instances will not change class when you declare a new class with the same name, and existing subclasses will not magically inherit from the new class.

Probably the simplest method to deal with subclasses is to also re-declare them, so they inherit from the "renewed" base class. An alternative would be to mess with their __bases__ property, although I can't tell you if that would have unexpected results (there will almost certainly be some corner cases where this would not work).

As to existing instances, it is possible to re-assign their __class__ property with a new class. This does present two issues - first you have to find them (see this question: Printing all instances of a class), and second of all, items stored in instance __dict__ or __slots__ properties will still be there in those instances. If that is not something that should happen with your new class definition, you will have to write appropriate code to handle that as part of the transformation.

IN summary, it's unlikely to be worth it except in quite simple cases. If you need complete uptime for a running system, you might be better using a replication-based approach to achieve code changes.

Update: If this is the kind of thing you know you're going to do, another solution would be to use the strategy pattern.

Community
  • 1
  • 1
Marcin
  • 48,559
  • 18
  • 128
  • 201
  • 1
    But what about instances of the first class? Subclasses of the first class? How do you update them? – agf Mar 22 '12 at 10:19
  • Instances of the class you undeclare or redefine are unaffected. By redefining or undeclaring you just affect the globally known identifier of the className. The compiled code of the class still lingers until no instance is using it anymore. You cannot change the code of existing instances. – Alfe Mar 22 '12 at 10:24
  • @Alfe Sorry, did you not read my answer? That information has been in my answer from the beginning. – Marcin Mar 22 '12 at 10:34
  • @Marcin I just answered agf's question in the comment above mine. – Alfe Mar 22 '12 at 14:28
  • @Alfe Once again, my answer already contained that information. – Marcin Mar 22 '12 at 14:30
  • @Marcin I was just answering somebody else's question who seemed to have overlooked that aspect of your long answer. What's your problem with me giving him an additional hint on what he asked? Yes you are right, your answer already contained that information. But to just tell agf that would have been rude. – Alfe Mar 22 '12 at 14:36
  • @Alfe My problem is that it implies that the information is missing or incorrect. – Marcin Mar 22 '12 at 14:55
  • Also, I'd add that @Alfe's comment is incorrect - as noted in the answer, you can actually change the class of existing instances. – Marcin Jan 20 '15 at 17:55
  • Did you get a badge for digging that topic up again? ;-) My comment used the word *change* in the meaning different to *ex*change: I'd say if you assign to `__class__`, you are *ex*changing the class and in the process *ex*change the code with a new one. You do not *change* the old code (which will still linger until nobody is using it), you just use a different one. But again, your answer wasn't lacking anything and my comment could use a little clarification. Assigning to `__class__` appears to me a little like putting a cheetah's skin on a leopard. Nothing I'd recommend. – Alfe Jan 22 '15 at 14:46
2

Undeclare a class using del className as usual.

Alfe
  • 56,346
  • 20
  • 107
  • 159
  • Hey Alfe, your answer doesn't mention that instances of the class you undeclare or redefine are unaffected. By redefining or undeclaring you just affect the globally known identifier of the className. The compiled code of the class still lingers until no instance is using it anymore. You cannot change the code of existing instances. – Marcin Mar 22 '12 at 10:35