I have a case where my class has a custom metaclass, which calls a class method of the class when creating it, something like:
class Metaclass(type):
def __new__(cls, name, bases, attrs):
...
new_class = super(Metaclass, cls).__new__(cls, name, bases, attrs)
...
new_class.get_fields() # do something
...
return new_class
class FooBar(object):
__metaclass__ = Metaclass
@classmethod
def get_fields(cls):
...
(Example of such code is in Tastypie.)
The problem is if I want to do:
class NewBar(FooBar):
@classmethod
def get_fields(cls):
super(NewBar, cls).get_fields()
...
This does not work because NewBar
is not yet created at the point super
is invoked (program flow is still in metaclass). So, is there any workaround?
I know that probably get_fields
method could become a method of metaclass, but this would make inheritance much harder to implement (you would have to define both new metaclass and class itself, not nice to developers wanting to extend this classes).
(Python 2.7.)
If NewBar
can be unavailable when get_fields
is invoked, you can still find it in the MRO of cls
:
@classmethod
def get_fields(cls):
# we can get invoked before NewBar is available in globals,
# so get NewBar from cls.__mro__
NewBar = next(c for c in cls.__mro__
if c.__module__ == __name__ and c.__name__ == 'NewBar')
super(NewBar, cls).get_fields()
...
Although this code looks funny, it works correctly and is significantly simpler than the alternatives proposed in the question. While most calls to super
with a non-constant first argument (such as unqualified super(cls, cls)
) are incorrect and break inheritance, this one is safe because the generator expression is nothing but an unconventional way to get a hold of NewBar
.
When looking for the clas in the MRO we check for both class and module name (available as __name__
, as pointed out by Mitar) to avoid a false positive if othermodule.NewBar
inherits from thismodule.NewBar
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With