

Improve Your Python: Metaclasses and Dynamic Classes With Type - lukashed
http://www.jeffknupp.com/blog/2013/12/28/improve-your-python-metaclasses-and-dynamic-classes-with-type/

======
JulianWasTaken
As he says himself at the end, these aren't used very often because they
aren't very useful.

The example at the end is perfectly well written using the class statement and
using register as a class decorator, while being more familiar and readable.

It gets tiring to hear people say "oh advanced Python? Like metaclasses, I'll
learn that".

Learn useful things instead, like writing readable, testable code.

~~~
dsj36
I think it was David Beazley who characterized metaclasses as "infecting" an
inheritance tree. If `class A` has a metaclass, then all subclasses of `A`
will inherit the metaclass as well. This behavior is _not_ shared by class
decorators, which only affect the decorated class.

So, I think this is a pretty reasonable place to use them -- getting magic
behavior from class decorators / metaclasses is bad enough, but getting
surprised when losing it upon subclassing is even worse!

~~~
jamesdutc
This "infectious behaviour" (though perhaps unfairly characterised) leads to
the clearest purpose of metaclasses.

Metaclasses (and build_class) is a mechanism by which to enforce a constraint
from a base type to a derived type.

(Note that, in practice, there is some trickiness around metaclasses on
derived classes: [http://seriously.dontusethiscode.com/2013/04/18/derived-
meta...](http://seriously.dontusethiscode.com/2013/04/18/derived-
metaclasses.html))

It's trivial to enforce a constraint from a derived type to a base type. e.g.,

    
    
        # base.py
        class Base:
            def spam(self): pass
    
        # derived.py
        class Derived(Base):
            assert hasattr(Base, 'spam') # or abc, &c.
            def ham(self):
                return self.spam
    

But how can we enforce a constraint in the other direction? (e.g.,
abc.ABCMeta)

    
    
        # base.py
        from functools import wraps
        
        class metaclass(type):
        	def __new__(m, n, b, d):
        		assert 'spam' in d # must implement, not just inherit
        
        		# can even enforce behaviour via wrapping
        		spam = d['spam']
        		@wraps(spam)
        		def wrap(*args, **kwargs):
        			print('wrap({}, {})'.format(args, kwargs))
        			return spam(*args, **kwargs)
        		d['spam'] = wrap
        
        		return type.__new__(m, n, b, d)
        
        class Base(metaclass=metaclass):
        	def spam(self): pass
        
        # derived.py
        class Derived(Base):
        	def spam(self): pass

------
temuze
Here's another amazing tutorial for metaclasses:
[http://stackoverflow.com/a/6581949/764463](http://stackoverflow.com/a/6581949/764463)

This is probably my all-time favorite StackOverflow post!

~~~
Tehnix
I actually prefer the StackOverflow post you linked over the OPs blog post
(not bashing on the blog post, the SO answer is just so good).

------
SpacemanSpiff
Did anyone pick up the OP's book, "Writing Idiomatic Python"? I'm tempted to
buy, as someone new to Python. Looks like it may be useful for learning some
Python best practices.

~~~
div
As luck would have it, I just bought and read "Writing Idiomatic Python"
earlier today.

It's a quick read and seems to be a nice shortcut to avoid a few newbie
pitfalls (I'm a Python newbie myself).

------
dmcg
I'd like to buy the book, but is it really necessary to enter my email and
password, twice each, then give my address, all to give you money through
PayPal?

