I guess this piece of code shouldn't work, but it works:
class Parent():
def print_child(self):
print(self.child_attr)
class Child(Parent):
child_attr = "Some text goes here"
child = Child()
child.print_child()
So the next question: what is the best practise?
leave it as it is (it seems not a good idea)
Define parent like:
class Parent():
child_attr = None
def print_child(self):
print(self.child_attr)
Define parent like:
class Parent():
def print_child(self, child_attr):
print(child_attr)
I have a Mixin class the lives in myModule.mixins. A new class in myModule.main (MyPaternalClass) is inheriting from myModule.mixins.MyMixin.
The purpose of this mixin is to generate new "child" objects given a string with the name of the child class, but the classes for these objects live in myModule.main, not in myModule.mixins
I understand how to do this when the Mixin lives in the same module using:
this = sys.modules[__name__]
cls = getattr(this, objType)
new_cls_inst = cls()
However I'm having trouble finding a good way to do this when the mixin class lives in its own module.
ex. myModule.mixins
class MyMixin(object):
def new_obj(self, objType):
cls = #Get the class
newobj = cls()
return newobj
Now, this mixin would be used in the following:
ex. myModule.main
from .mixin import MyMixin
class MyPaternalClass(MyMixin):
def __init__(self):
super(MyPaternalClass, self).__init__()
self.children = []
def add_child(self, child_type):
self.children.append(self.new_obj(child_type))
class Son(object):
def __init__(self):
pass
class Daughter(object):
def __init__(self):
pass
The usage would look similar to this:
new_parent = MyPaternalClass()
new_parent.add_child('Son')
new_parent.add_child('Daughter')
The reason the mixin class can't live in the same module is because it's intended to be used generically in several other modules.
I would like for child process to have certain properties, but since you can't force child methods to inherit the property decorator, I want to at least assert that these attributes of the child are properties of the class.
Something like this:
class Parent:
def __init__(self):
assert isinstance(self.foo, property)
def foo(self):
raise NotImplementedError
class Child(Parent):
def __init__(self):
super().__init__()
#property
def foo(self):
return 'bar'
But of course by the time Parent.__init__() is run, self.foo has become 'bar' and there is an AssertionError. Is there a way to accomplish what I'm going for using meta classes? If so, can it be that the Parent class is the one that inherits the metaclass, not the Child?
I found a solution. Instead of testing whether self.foo is a property, I tested whether it was not a bound method:
from inspect import ismethod
class Parent:
def __init__(self):
assert not ismethod(self.foo, property)
def foo(self):
raise NotImplementedError
This will work for most cases, but will fail if the property being returned by Child.foo is itself a bound method. Still open to more complete answers.
I have a python abstract base class as follows:
class Node(object):
"""
All concrete node classes should inherit from this
"""
__metaclass__ = ABCMeta
def __init__(self, name):
self.name = name
self.inputs = dict()
def add_input(self, key, value=None, d=None):
self.inputs[key] = (d, value)
def bind_input(self):
print "Binding inputs"
#abstractmethod
def run(self):
pass
Now, various derived classes will inherit from this node class and override the run method. It is always the case that bind_input() must be the first thing that should be called in the run method. Currently, for all derived classes the developer has to make sure to first call self.bind_input(). This is not a huge problem per se but out of curiosity is it possible to ensure this somehow from the base class itself that bind_input is called before executing the child object's run?
The usual object-oriented approach is this:
def run(self):
self.bind_input()
return self.do_run()
#abstractmethod
def do_run(self):
pass # override this method
Have your subclasses override the inner method, instead of the outer one.
If you have multiple layers of inheritance and know that a particular variable exists, is there a way to trace back to where the variable originated? Without having to navigate backwards by looking through each file and classes. Possibly calling some sort of function that will do it?
Example:
parent.py
class parent(object):
def __init__(self):
findMe = "Here I am!"
child.py
from parent import parent
class child(parent):
pass
grandson.py
from child import child
class grandson(child):
def printVar(self):
print self.findMe
Try to locate where the findMe variable came from with a function call.
If the "variable" is an instance variable - , so , if at any point in chain of __init__ methods you do:
def __init__(self):
self.findMe = "Here I am!"
It is an instance variable from that point on, and cannot, for all effects, be made distinct of any other instance variable. (Unless you put in place a mechanism, like a class with a special __setattr__ method, that will keep track of attributes changing, and introspect back which part of the code set the attribute - see last example on this answer)
Please also note that on your example,
class parent(object):
def __init__(self):
findMe = "Here I am!"
findMe is defined as a local variable to that method and does not even exist after __init__ is finished.
Now, if your variable is set as a class attribute somewhere on the inheritance chain:
class parent(object):
findMe = False
class childone(parent):
...
It is possible to find the class where findMe is defined by introspecting each class' __dict__ in the MRO (method resolution order) chain . Of course, there is no way, and no sense, in doing that without introspecting all classes in the MRO chain - except if one keeps track of attributes as defined, like in the example bellow this - but introspecting the MRO itself is a oneliner in Python:
def __init__(self):
super().__init__()
...
findme_definer = [cls for cls in self.__class__.__mro__ if "findMe" in cls.__dict__][0]
Again - it would be possible to have a metaclass to your inheritance chain which would keep track of all defined attributes in the inheritance tree, and use a dictionary to retrieve where each attribute is defined. The same metaclass could also auto-decorate all __init__ (or all methods), and set a special __setitem__ so that it could track instance attributes as they are created, as listed above.
That can be done, is a bit complicated, would be hard to maintain, and probably is a signal you are taking the wrong approach to your problem.
So, the metaclass to record just class attributes could simply be (python3 syntax - define a __metaclass__ attribute on the class body if you are still using Python 2.7):
class MetaBase(type):
definitions = {}
def __init__(cls, name, bases, dct):
for attr in dct.keys():
cls.__class__.definitions[attr] = cls
class parent(metaclass=MetaBase):
findMe = 5
def __init__(self):
print(self.__class__.definitions["findMe"])
Now, if one wants to find which of the superclasses defined an attribute of the currentclass, just a "live" tracking mechanism, wrapping each method in each class can work - it is a lot trickier.
I've made it - even if you won't need this much, this combines both methods - keeping track of class attributes in the class'class definitions and on an instance _definitions dictionary - since in each created instance an arbitrary method might have been the last to set a particular instance attribute: (This is pure Python3, and maybe not that straighforward porting to Python2 due to the "unbound method" that Python2 uses, and is a simple function in Python3)
from threading import current_thread
from functools import wraps
from types import MethodType
from collections import defaultdict
def method_decorator(func, cls):
#wraps(func)
def wrapper(self, *args, **kw):
self.__class__.__class__.current_running_class[current_thread()].append(cls)
result = MethodType(func, self)(*args, **kw)
self.__class__.__class__.current_running_class[current_thread()].pop()
return result
return wrapper
class MetaBase(type):
definitions = {}
current_running_class = defaultdict(list)
def __init__(cls, name, bases, dct):
for attrname, attr in dct.items():
cls.__class__.definitions[attr] = cls
if callable(attr) and attrname != "__setattr__":
setattr(cls, attrname, method_decorator(attr, cls))
class Base(object, metaclass=MetaBase):
def __setattr__(self, attr, value):
if not hasattr(self, "_definitions"):
super().__setattr__("_definitions", {})
self._definitions[attr] = self.__class__.current_running_class[current_thread()][-1]
return super().__setattr__(attr,value)
Example Classes for the code above:
class Parent(Base):
def __init__(self):
super().__init__()
self.findMe = 10
class Child1(Parent):
def __init__(self):
super().__init__()
self.findMe1 = 20
class Child2(Parent):
def __init__(self):
super().__init__()
self.findMe2 = 30
class GrandChild(Child1, Child2):
def __init__(self):
super().__init__()
def findall(self):
for attr in "findMe findMe1 findMe2".split():
print("Attr '{}' defined in class '{}' ".format(attr, self._definitions[attr].__name__))
And on the console one will get this result:
In [87]: g = GrandChild()
In [88]: g.findall()
Attr 'findMe' defined in class 'Parent'
Attr 'findMe1' defined in class 'Child1'
Attr 'findMe2' defined in class 'Child2'