make a cat. In [1]: class Cat(object): pass grumpy = Cat() grumpy Oops. Forgot to include cat-like features. But we can add on. In [2]: Cat.sound = 'meow' def some_function(self): print self.sound Cat.speak = some_function grumpy.speak() Let's turn Grumpy into a dog. Out[1]: <__main__.Cat at 0x10df1c3d0> meow
grumpy.__class__ = Dog grumpy.speak() Grumpy is not happy about being a dog. In [4]: grumpy.sound = 'meh' grumpy.speak() If Grumpy is an instance of Dog... In [5]: type(grumpy) then Dog must be an instance of ... type In [6]: type(Dog) type is just a class whose instances are other classes. Since it's a class, we can subclass type. woof meh Out[5]: __main__.Dog Out[6]: type
factory(cls): # not available on the Cat instance! return cls() Class definition is just fancy syntax for instantiating a metaclass. In [8]: class FancyCat(Cat): __metaclass__ = MetaCat # Py2 syntax type(FancyCat) In [9]: FancyCat In [10]: grumpy.__class__ = FancyCat grumpy.speak() grumpy In [11]: FancyCat.factory() Out[8]: __main__.MetaCat Out[9]: meh Out[10]: < at 0x10df1c3d0> Out[11]: < at 0x10df1c090>
metaclass? It's fun. What else are you gonna do? It unifies classes and objects. (Actually useful stuff.) tl;dr Classes are dynamic structures. Classes are instances. Be stupid! Silly, useless code is the best way to learn! [email protected] @SoylentBleen -------------------------------------------------------------------- ------- AttributeError Traceback (most recent cal l last) <ipython-input-12-1710632cd721> in <module>() ----> 1 grumpy.factory() # this does not work, yay! AttributeError: 'FancyCat' object has no attribute 'factory'