Skip to content

Instantly share code, notes, and snippets.

@huangsam
Last active January 30, 2019 03:49
Show Gist options
  • Save huangsam/372da09da5361d34fcce39ead7c01d42 to your computer and use it in GitHub Desktop.
Save huangsam/372da09da5361d34fcce39ead7c01d42 to your computer and use it in GitHub Desktop.
Metaclasses in action
class MetaOne(type):
def __new__(mcs, name, bases, attrs):
kls = super().__new__(mcs, name, bases, attrs)
kls._numbers = [1, 2, 3]
return kls
class MetaTwo(type):
def __new__(mcs, name, bases, attrs):
kls = super().__new__(mcs, name, bases, attrs)
kls._numbers = {1, 2, 3}
return kls
class A(metaclass=MetaOne):
pass
class B(metaclass=MetaOne):
pass
assert hasattr(A, '_numbers')
assert hasattr(B, '_numbers')
assert A._numbers == B._numbers == [1, 2, 3]
try:
class C(A, metaclass=MetaTwo):
pass
except TypeError:
print('Metaclass conflict exists between A and C')
class D:
pass
class E:
pass
class F(D, E, metaclass=MetaOne):
pass
class ModelRegistry:
models = {}
class ModelMeta(type):
@classmethod
def __prepare__(mcs, name, bases):
print('PRE', mcs, name, bases)
return {'xyz': 4}
def __new__(mcs, name, bases, attrs):
print('NEW', mcs, name, bases, attrs)
fields = {}
for k, v in attrs.items():
if isinstance(v, int):
fields[k] = v
for base in bases:
if hasattr(base, '_fields'):
fields.update(base._fields)
attrs['_fields'] = fields
kls = super().__new__(mcs, name, bases, attrs)
if kls.__name__ != 'Model':
ModelRegistry.models[name] = kls
return kls
def __init__(cls, *args, **kwargs):
cls._jk = 'lol'
class CustomMeta(ModelMeta):
pass
class Model(metaclass=ModelMeta):
pass
class A(Model):
foo = 1
class B(A):
bar = 2
class C(metaclass=CustomMeta):
reg = 3
print(A._fields)
print(B._fields)
print(B._jk)
print(ModelRegistry.models)
@huangsam
Copy link
Author

This code is a variation of an answer found in the following SO post: https://stackoverflow.com/questions/392160/what-are-some-concrete-use-cases-for-metaclasses

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment