Created
May 6, 2018 13:24
-
-
Save obriencj/40adc3f6db4d32ea04d5d61e9b25feb5 to your computer and use it in GitHub Desktop.
building classes in python
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def sample_1(parent=object): | |
class Sample(parent): | |
def __init__(self, val=None): | |
self.value = val | |
return Sample | |
def sample_2(parent=object): | |
class Sample(parent): | |
def __init__(self, val=None): | |
super().__init__(self) | |
self.value = val | |
return Sample | |
from dis import dis, show_code | |
from types import CodeType | |
def disassemble(obj, verbose=False): | |
if verbose: | |
show_code(obj) | |
print("Disassembly:") | |
dis(obj) | |
def find_code_const(obj, name): | |
obj = getattr(obj, "__code__", obj) | |
for c in obj.co_consts: | |
if isinstance(c, CodeType): | |
if c.co_name == name: | |
return c | |
else: | |
return None | |
# Sample1 = sample_1(object) | |
Sample1_class_code = find_code_const(sample_1, "Sample") | |
Sample1_init_code = find_code_const(Sample1_class_code, "__init__") | |
# Sample2 = sample_2(object) | |
Sample2_class_code = find_code_const(sample_2, "Sample") | |
Sample2_init_code = find_code_const(Sample2_class_code, "__init__") | |
if __name__ == "__main__": | |
print("\n === Sample1 class code ===") | |
disassemble(Sample1_class_code, True) | |
print("\n === Sample1 init code ===") | |
disassemble(Sample1_init_code, True) | |
print("\n === Sample2 class code ===") | |
disassemble(Sample2_class_code, True) | |
print("\n === Sample2 init code ===") | |
disassemble(Sample2_init_code, True) | |
# yuck. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This is how the python 3.6 variation of a no-argument
super()
was implemented. When detected at compile time, it causes the compiler to inject a closure for a value named__class__
into any method code which uses the super. That__class__
closure is then captured in the class' namespace as the__classcell__
. Thetype()
call which creates a type from the namespace resulting from calling the class code will check for the cell in a__classcell__
attribute, and if it finds one, will set the cell contents to the resulting class instance that type has created.