I am well aware of fact that classes can be declared dynamically in python using type and have used it here and there. But I am still unclear what are the differences between these two functions.
def class_factory():
def init(self, attr):
self.attr = attr
class_ = type('DynamicClass', (), {'__init__' : init})
return class_
and
def class_factory():
class DynamicClass:
def __init__(self, attr):
self.attr = attr
return DynamicClass
I have seen first pattern used in a lot of code-bases (like django) but never seen second one so far. Still I find second one more clear, syntactically.
I am struggling to find proper explanation about why people use first pattern for declaring dynamic classes and not second one. I experimented with both functions and could not find any notable differences between classes obtained from both functions. I am hoping for a clear explanation about differences between above two patterns/syntaxes from any aspect (performance-wise or any other) they differ.
Thanks,
A
classstatement is a declarative syntax for a call to a metaclass.is equivalent to
where
{...}is some mapping constructed from the body of theclassstatement. Just as a simple example, without going into full detail:would define a function name
__init__, then pass{'__init__': __init__, 'some_attr': 'foo string'}toSomeMeta. The name__init__only exists in a temporary namespace created by theclassstatement, without affecting any name__init__that might exist outside the statement.To answer your question, sometimes it is more flexible or simpler to construct the third argument the metaclass yourself than to let the
classstatement do it for you. The same goes for the second argument. The first argument is fixed by the syntax of theclassstatement, but could be generated at run-time if you call the metaclass yourself.Note that this means you can really abuse the
classstatement.EnumMetafrom theenummodule, in my opinion, stretches what you should do with one. Here's a really abusive example. The metaclass doesn't actually have to be a type; it just has to be callable, and it needs to accept three positional arguments. It can accept additional keyword arguments as well. It can then do anything it wants with those arguments, and return anything it wants as well.Fooisn't even a class; it's bound to3.