Skip to content

Instantly share code, notes, and snippets.

@JonnyWaffles
Last active June 14, 2020 16:33
Show Gist options
  • Save JonnyWaffles/dbbb445b174c398909bfb6eab6081497 to your computer and use it in GitHub Desktop.
Save JonnyWaffles/dbbb445b174c398909bfb6eab6081497 to your computer and use it in GitHub Desktop.
Demo of how the underlying Python object model works because I always forget and need to re-read it
class MyMetaClass(type):
def __new__(cls, name, bases, attrs):
"""
Step 1:
Called when the module is loaded and class definitions are read.
Prepares the new type MyObj.
cls is MyMetaclass, name, bases, and attrs is the code
in the class definition, aka name, bases, attrs
"""
print(f'Messagee 1: Hi from meta new')
assert name == 'MyObj'
assert bases == ()
assert attrs['cls_attr'] == 'my class attribute'
my_obj_cls = super().__new__(cls, name, bases, attrs)
return my_obj_cls
def __call__(cls, *args, **kwargs):
"""
Step 2: Called when a child class is instantiated. Consider this a metahook for object creation.
args and kwargs are whatever data will eventually be passed to the instances init
Args:
*args:
**kwargs:
Returns:
"""
assert cls is MyObj
print(f'Message 3: hi from meta call {args}, {kwargs}')
instance = super().__call__(*args, **kwargs)
print('Message 6: Return the object instance from meta call')
assert isinstance(instance, MyObj)
return instance
class MyObj(metaclass=MyMetaClass):
cls_attr = 'my class attribute'
def __new__(cls, *args, **kwargs):
"""Creates a new instance of MyObj and
then passes it init.
Note *args and **kwargs is the same data sent to init
"""
print('Message 4: hi from MyObj new')
assert args == ('arg1', 'arg2')
assert kwargs == {'kwarg1': 'val1', 'kwarg2': 'val2'}
assert isinstance(cls, MyMetaClass)
assert type(cls) is MyMetaClass
new = super().__new__
# Under the hood we're using object to create a new instance of cls
assert new is object.__new__
# Return an instance of cls so init is triggered
instance = new(cls)
return instance
def __init__(self, *args, **kwargs):
print('Message 5: hi from MyObj init')
assert args == ('arg1', 'arg2')
assert kwargs == {'kwarg1': 'val1', 'kwarg2': 'val2'}
print('Message 2: Prior to instantiating MyObj instance')
obj = MyObj('arg1', 'arg2', kwarg1='val1', kwarg2='val2')
assert isinstance(obj, MyObj)
print('Message 7: All one')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment