wtfpython
wtfpython copied to clipboard
Changing the type of an object at runtime
Surprisingly, Python allows you to change the __class__ attribute of an object:
In [1]: class A:
...: def __init__(self):
...: self.x = 5
...: self.y = "hi"
...:
...: class B:
...: def doit(self):
...: print(self.x, self.y)
...:
In [2]: a = A()
In [3]: a.doit()
AttributeError: 'A' object has no attribute 'doit'
In [4]: a.__class__ = B
In [5]: a.doit()
5 hi
In [6]: a.__class__ = A
In [7]: a.doit()
AttributeError: 'A' object has no attribute 'doit'
This example was rather simple, but things grow more complicated when inheritance is involved. On the other hand, this proves that Python instances are mere dicts... :). With a few exceptions though.
Wow, yes, it can get complicated with inheritance. This can also be a way to bypass any validations / attribute assignments that might happen in the __init__ method of class B.
class Backdoor:
def __init__(self, target_class):
self.__class__ = target_class
class B:
def __init__(self, email, pwd):
self.email = self.validate_email()
self.pwd = self.validate_pwd()
def validate_email(self, email):
pass
def validate_pwd(self, pwd):
pass
In [18]: b = Backdoor(B)
In [19]: type(b)
Out[19]: __main__.B
I can write an example snippet, and add some caveats of this "feature" (differences across Python versions, handling of __slots__, ...)
Sure, that'd be awesome, looking forward to your PR :)