I'm learning meta programming in python 3. My professor did give us this exercise:
Write the metaclass Spell that transforms the instances of Student in a Wizard.
I did this:
class Spell(type):
def __new__(cls, classname, supers, cls_dict):
cls_dict['__init__'] = Spell.toWizard()
cls_dict['__qualname__'] = 'wizard'
return type.__new__(cls, 'wizard', supers, cls_dict)
@staticmethod
def toWizard():
def init(*args):
wizard(args, 'fire_spell')
return init
class student(metaclass=Spell):
def __init__(self, name):
self.name = name
class person():
def __init__(self, name):
self.name = name
class wizard(person):
def __init__(self, name, magic):
self.magic = magic
super().__init__(name)
if __name__ == '__main__':
s = student('name1')
print(s.__dict__)
s = student('name2')
print(s.__dict__)
The wizard class __init__
is correctly being called instead of student class __init__
, however the objects created have an empty __dict__
. Where am I going wrong?
Your init()
replacement function creates a local wizard()
instance, and doesn't return anything:
def init(*args):
wizard(args, 'fire_spell')
That's a separate instance, self
is not touched.
Don't use __new__
; that produces a new class. You only renamed the student
class and gave it an ineffectual __init__
method.
Override the __call__
method to hook into creating the instances. There you can replace or ignore the first argument, which is the student
class object and use the wizard
class in its place:
class Spell(type):
def __call__(cls, *args, **kwargs):
# ignore the cls argument, return a wizard instead
if 'magic' not in kwargs and len(args) < 2:
# provide a default magic value
kwargs['magic'] = 'fire_spell'
return wizard(*args, **kwargs)
Because student
only takes a single argument normally, so the above adds a magic
argument if none is specified.
Demo:
>>> student('name1')
<__main__.wizard object at 0x10f1e8198>
>>> vars(_)
{'magic': 'fire_spell', 'name': 'name1'}
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