Gist for: exploring_inheritance_in_python.py
Source Code
# the one and only Dev.E.L'Peer https://github.com/develpeer
##
# This gist explores class inheritance including multiple inheritance
##
import json
from multiprocessing.util import abstract_sockets_supported
from exploring_python_classes import MY_DERIVED_CLASS
class BABY_BASE:
"""I find Class:BabyBase and Object:baby_base incosistent"""
base_class_var = 100.1
def __init__(this, param):
print("BC:constructor")
this.base_object_var_1 = 101
this.base_object_var_2 = param
this.base_object_var_3 = param
def __repr__(this) -> str:
d = vars(this)
d["base_class_var"] = this.base_class_var
d["CLASS"] = this.__class__.__name__
return json.dumps(d,indent=4)
def abstract_func(this):
raise Exception("No implementation")
class DERIVED_CLASS_1(BABY_BASE):
def __init__(this, param):
#have to explicitly call super contructor. but really you can call any function here
print("DC1:constructor")
BABY_BASE.__init__(this,param)
this.base_object_var_3 = this.base_object_var_2 + .50
this.derived_object_var_3 = this.base_class_var *2
this.derived_object_var_4 = param
class DERIVED_CLASS_2(BABY_BASE):
def __init__(this, param):
print("DC2:constructor")
super().__init__(param)
this.base_object_var_3 = this.base_object_var_2 + .75
this.derived_object_var_3 = this.base_class_var *3
this.derived_object_var_5 = param
def abstract_func(this):
return "Yes implementation"
def regular_func(this):
return "Just some random value:"+super()
class DERIVED_GRAND_CHILD(DERIVED_CLASS_1,DERIVED_CLASS_2):
pass
bb = BABY_BASE(100)
print("bb:",bb)
print("isinstance(bb,BABY_BASE)",isinstance(bb,BABY_BASE))
print("issubclass(BABY_BASE,BABY_BASE)",issubclass(BABY_BASE,BABY_BASE))
do = DERIVED_CLASS_1(200)
print("do:",do)
try:
do.abstract_func()
except BaseException as e:
print("Above line should throw an error:",e)
print("isinstance(do,BABY_BASE)",isinstance(do,BABY_BASE))
print("issubclass(DERIVED_CLASS_1,BABY_BASE)",issubclass(DERIVED_CLASS_1,BABY_BASE))
do2 = DERIVED_CLASS_2(300)
print("do2:",do2)
do2.abstract_func()
print("isinstance(do2,BABY_BASE)",isinstance(do2,BABY_BASE))
print("issubclass(DERIVED_CLASS_2,BABY_BASE)",issubclass(DERIVED_CLASS_2,BABY_BASE))
ddc = DERIVED_GRAND_CHILD(400)
#Will invoke the first class' constructor and the second class' methods when the clash
#makes complete sense right?
print("ddc",ddc)
print(ddc.abstract_func()) #This is from the second parent, not the first!!
class B:
def f(self):
return "p"
class C1(B):
#no definition of f
pass
class C2(B):
def f(self):
return "c2"
class G(C1,C2):
pass
##For most purposes, in the simplest cases, you can
# think of the search for attributes inherited from a
# parent class as depth-first, left-to-right,
# not searching twice in the same class where
# there is an overlap in the hierarchy. Thus, if an
# attribute is not found in DerivedClassName, it is
# searched for in Base1, then (recursively) in the base
# classes of Base1, and if it was not found there, it
# was searched for in Base2, and so on.
### I call bullshit ...> This is not depth first, left to right
### A depth first would have returned "p"
print("WTF python:",G().f())
class T:
"hello world"
t = T()
print("instance of T:",t)
print("t.doc:",t.__doc__)
print(BABY_BASE.__dict__)
Output
After running the above code snippet, you will get this output
>>>
>>> classvar:100, #class var accessed via class
>>> classvar_2:200, #class var accessed via class
>>> o_var_1:300,
>>> o_var_2:3.14,
>>>
>>> ----------------------------------------
>>> All the attribites of o:
>>> __class__
>>> copyGists.sh rebuild.sh __delattr__
>>> copyGists.sh rebuild.sh __dict__
>>> copyGists.sh rebuild.sh __dir__
>>> copyGists.sh rebuild.sh __doc__
>>> copyGists.sh rebuild.sh __eq__
>>> copyGists.sh rebuild.sh __format__
>>> copyGists.sh rebuild.sh __ge__
>>> copyGists.sh rebuild.sh __getattribute__
>>> copyGists.sh rebuild.sh __gt__
>>> copyGists.sh rebuild.sh __hash__
>>> copyGists.sh rebuild.sh __init__
>>> copyGists.sh rebuild.sh __init_subclass__
>>> copyGists.sh rebuild.sh __le__
>>> copyGists.sh rebuild.sh __lt__
>>> copyGists.sh rebuild.sh __module__
>>> copyGists.sh rebuild.sh __ne__
>>> copyGists.sh rebuild.sh __new__
>>> copyGists.sh rebuild.sh __private_var__
>>> copyGists.sh rebuild.sh __reduce__
>>> copyGists.sh rebuild.sh __reduce_ex__
>>> copyGists.sh rebuild.sh __repr__
>>> copyGists.sh rebuild.sh __setattr__
>>> copyGists.sh rebuild.sh __sizeof__
>>> copyGists.sh rebuild.sh __str__
>>> copyGists.sh rebuild.sh __subclasshook__
>>> copyGists.sh rebuild.sh __weakref__
>>> copyGists.sh rebuild.sh class_var
>>> copyGists.sh rebuild.sh class_var_2
>>> copyGists.sh rebuild.sh f1
>>> copyGists.sh rebuild.sh f2
>>> copyGists.sh rebuild.sh o_var_1
>>> copyGists.sh rebuild.sh o_var_2
>>> ----------------------------------------
>>> All the attribites of MyFirstClass:
>>> __class__
>>> copyGists.sh rebuild.sh __delattr__
>>> copyGists.sh rebuild.sh __dict__
>>> copyGists.sh rebuild.sh __dir__
>>> copyGists.sh rebuild.sh __doc__
>>> copyGists.sh rebuild.sh __eq__
>>> copyGists.sh rebuild.sh __format__
>>> copyGists.sh rebuild.sh __ge__
>>> copyGists.sh rebuild.sh __getattribute__
>>> copyGists.sh rebuild.sh __gt__
>>> copyGists.sh rebuild.sh __hash__
>>> copyGists.sh rebuild.sh __init__
>>> copyGists.sh rebuild.sh __init_subclass__
>>> copyGists.sh rebuild.sh __le__
>>> copyGists.sh rebuild.sh __lt__
>>> copyGists.sh rebuild.sh __module__
>>> copyGists.sh rebuild.sh __ne__
>>> copyGists.sh rebuild.sh __new__
>>> copyGists.sh rebuild.sh __private_var__
>>> copyGists.sh rebuild.sh __reduce__
>>> copyGists.sh rebuild.sh __reduce_ex__
>>> copyGists.sh rebuild.sh __repr__
>>> copyGists.sh rebuild.sh __setattr__
>>> copyGists.sh rebuild.sh __sizeof__
>>> copyGists.sh rebuild.sh __str__
>>> copyGists.sh rebuild.sh __subclasshook__
>>> copyGists.sh rebuild.sh __weakref__
>>> copyGists.sh rebuild.sh class_var
>>> copyGists.sh rebuild.sh class_var_2
>>> copyGists.sh rebuild.sh f1
>>> copyGists.sh rebuild.sh f2
>>> 'MY_FIRST_CLASS' object has no attribute 'o_var_1'
>>> !!!!You can delete attributes of an object from outside the object.. WTF!!
>>> So much for encapsulation
>>> MY_FIRST_CLASS.f1 <function MY_FIRST_CLASS.f1 at 0x10aa769e0>
>>> MY_FIRST_CLASS.f1() you get what you so.. do not deserve
>>> o.f1 <bound method MY_FIRST_CLASS.f1 of
>>> classvar:100, #class var accessed via class
>>> classvar_2:200, #class var accessed via class
>>> o_var_1:UNDEFINED,
>>> o_var_2:3.14,
>>> >
>>> I got me some args y'all, because python uses an implicit invocation context to differentiate betwwen instance and class methods
>>> That is if this method is an object method, you must declare its firt arg as 'self', which fuck that ..i'm going tojust call python_sucks..see next method
>>> Stupid stupid python arg =
>>> classvar:100, #class var accessed via class
>>> classvar_2:200, #class var accessed via class
>>> o_var_1:UNDEFINED,
>>> o_var_2:3.14,
>>>
>>> o.f1 you get what you so.. do not deserve
>>> o.f2 <bound method MY_FIRST_CLASS.f2 of
>>> classvar:100, #class var accessed via class
>>> classvar_2:200, #class var accessed via class
>>> o_var_1:UNDEFINED,
>>> o_var_2:3.14,
>>> >
>>> o.f2 returned 314.0
>>> invoking the method at class level will cause a TypeError
>>> This should work just fine. 'of2' is bound to 'o': 314.0
>>> Class variables can be accessed in one of two ways outside the class definition: True
>>> {'o_var_1': 300, 'o_var_2': -200} 100 200 -20000
>>> BC:constructor
>>> bb: {
>>> "base_object_var_1": 101,
>>> "base_object_var_2": 100,
>>> "base_object_var_3": 100,
>>> "base_class_var": 100.1,
>>> "CLASS": "BABY_BASE"
>>> }
>>> isinstance(bb,BABY_BASE) True
>>> issubclass(BABY_BASE,BABY_BASE) True
>>> DC1:constructor
>>> BC:constructor
>>> do: {
>>> "base_object_var_1": 101,
>>> "base_object_var_2": 200,
>>> "base_object_var_3": 200.5,
>>> "derived_object_var_3": 200.2,
>>> "derived_object_var_4": 200,
>>> "base_class_var": 100.1,
>>> "CLASS": "DERIVED_CLASS_1"
>>> }
>>> Above line should throw an error: No implementation
>>> isinstance(do,BABY_BASE) True
>>> issubclass(DERIVED_CLASS_1,BABY_BASE) True
>>> DC2:constructor
>>> BC:constructor
>>> do2: {
>>> "base_object_var_1": 101,
>>> "base_object_var_2": 300,
>>> "base_object_var_3": 300.75,
>>> "derived_object_var_3": 300.29999999999995,
>>> "derived_object_var_5": 300,
>>> "base_class_var": 100.1,
>>> "CLASS": "DERIVED_CLASS_2"
>>> }
>>> isinstance(do2,BABY_BASE) True
>>> issubclass(DERIVED_CLASS_2,BABY_BASE) True
>>> DC1:constructor
>>> BC:constructor
>>> ddc {
>>> "base_object_var_1": 101,
>>> "base_object_var_2": 400,
>>> "base_object_var_3": 400.5,
>>> "derived_object_var_3": 200.2,
>>> "derived_object_var_4": 400,
>>> "base_class_var": 100.1,
>>> "CLASS": "DERIVED_GRAND_CHILD"
>>> }
>>> Yes implementation
>>> WTF python: c2
>>> instance of T: <__main__.T object at 0x10aa6d2d0>
>>> t.doc: hello world
>>> {'__module__': '__main__', '__doc__': 'I find Class:BabyBase and Object:baby_base incosistent', 'base_class_var': 100.1, '__init__': <function BABY_BASE.__init__ at 0x10aa767a0>, '__repr__': <function BABY_BASE.__repr__ at 0x10aa76b00>, 'abstract_func': <function BABY_BASE.abstract_func at 0x10aa76b90>, '__dict__': <attribute '__dict__' of 'BABY_BASE' objects>, '__weakref__': <attribute '__weakref__' of 'BABY_BASE' objects>}