Init child with Parent instance - python

I have a function which return instances of the class Parent:
def generateParent():
do_stuff
return Parent(some_parameters)
Now I want to init a subclass of Parent with the results of a call to generateParent():
class Child(Parent):
def __new__():
return generateParent(some_other_parameters)
The problem is, when I override some methods from Parent in Child and then call them in instances of Child in my program, the original Parent method gets called instead of the new one from Child. Am I doing something wrong here? Am I using the correct design here for my task?
EDIT: I don't have access neither to Parent nor generateParent()
Solution(thanks to #Paul McGuire's answer):
class Child(object):
def __init__(self):
self.obj = generateParent()
def __getattr__(self, attr):
return getattr(self.obj, attr)

Since generateParent is not your code, then instead of inheritance, you might want to use containment and delegation. That is, instead of defining a subclass, define a wrapper class that contains the generated object, forwards method calls to it when needed, but can add new behavior or modified behavior in the wrapper.
In this question, the OP had a similar situation, having a class generated in a libary, but wanting to extend the class and/or modify some behavior of the class. Look at how I added a wrapper class in that question, and you might consider doing something similar here.

Here's one way to do it:
def generateChild(params):
p = generateParent(params)
p.__class__ = Child
return p
class Child(Parent):
# put method overrides etc here
childinstance = generateChild(some_params)

Perhaps you want generateParent to be able to make instances of other classes:
def generateParent(cls=Parent):
do_stuff
return cls(some_parameters)
Now this will make a Child object:
child = generateParent(Child)
Or perhaps you want Parent and all of its derived classes to use common initialization code?
class Parent(object):
def __init__(self):
do_stuff
# init from some_parameters
class Child(Parent):
# blah..
Make your Child object able to copy information from a created Parent object:
class Child(Parent):
def __init__(self):
model_parent = generateParent()
self.a = model_parent.a
self.b = model_parent.b
# etc.

Related

Is it possible for a class to provide convenient direct access to the methods of specific objects initialised within it?

This may be highly abnormal, but I feel like it may be a useful thing. I have a range of classes that do different jobs in my package. I want to keep them seperate to keep the logic modular, and allow advanced users to use the classess directly, but I also want users to have a main convenience class that gives them quick access to the methods defined in these other classes. So to provide an example, currently this works...
class Tail:
def wag_tail(self):
print('Wag Wag')
class Dog:
def __init__(self):
self.tail = Tail()
my_dog = Dog()
my_dog.tail.wag_tail()
>> Wag Wag
But... is it possible to adjust my Dog class so that this also works?
my_dog.wag_tail()
>> Wag Wag
Editing for clarity.
I want to achieve the above, but automatically, without necessarily having to define a new method in Dog e.g. you could manually ensure access via def wag_tail(self): self.tail.wag_tail(), but what if I wanted to avoid writing a convenience access method every time I add a method to my Tail class. Is there a way to set things up such that Tail methods are always accessible from Dog?
I have done something similar. You can pass in the owning class to the __init__ of the method class and have it append it's method back to the owning class.
Here any class that inherits from PassThrough will run through it's own attributes and append any public methods to a parent class. You just have to pass the self of the owning class.
class PassThrough:
def __init__(self, parent=None):
if not parent:
return
for method_name in dir(self):
if not method_name.startswith('_'):
method = getattr(self, method_name)
setattr(parent, method_name, method)
class Tail(PassThrough):
def wag_tail(self):
print('Wag Wag')
class Dog:
def __init__(self):
self.tail = Tail(self)
dog = Dog()
dog.wag_tail()
# prints: Wag Wag
You can also pass methods upward through multiple layers by using super(). Here we create a Tongue class, and then a Head class that has a tongue. Then add a head to the Dog class.
class Tongue(PassThrough):
def lick(self):
print('Lick Lick')
class Head(PassThrough):
def __init__(self, parent):
self.tongue = Tongue(self)
# this passes the appended method from Tongue to the parent.
super().__init__(parent)
def shake_head(self):
print('Fwop fwop')
class Dog:
def __init__(self):
self.tail = Tail(self)
self.head = Head(self)
dog = Dog()
dog.lick()
dog.shake_head()
This is what the __getattr__ special method is made for:
class Tail:
def wag_tail(self):
print('Wag Wag')
class Dog:
def __init__(self):
self.tail = Tail()
# Only new code is this two-line method definition
def __getattr__(self, name):
return getattr(self.tail, name)
__getattr__ is called when an attribute (including method) is looked up on an instance and the attribute is not found; when that happens, the __getattr__ is invoked with an argument of the name being looked for. The getattr built-in function can then be used to look it up on contained object(s).
If you have many such contained classes, you'll need to define some absolute ordering for checking, and check them one-by-one, so if you needed to check for behaviors of self.tongue and self.paw for instance, in that order, you might implement it as:
def __getattr__(self, name):
for internalname in ('tail', 'tongue', 'paw'):
internalattr = getattr(self, internalname)
try:
return getattr(internalattr, name)
except AttributeError:
continue # Try the next
raise AttributeError(name)
One caveat: When looking up special methods (those that begin and end with __, usually used to implement features that Python uses implicitly via syntax or built-in functions, e.g. __len__ for len(x) and __add__ for x + y), Python typically bypasses instance lookup, along with the special attribute access interception methods (__getattr__ and __getattribute__), so you can't use this to handle operator overloading and the like. In that case, you'll have to hand-write (or programmatically generate code for and eval) the proxying methods individually.

correct way of extending a class in python

I am given a designated factory of A-type objects. I would like to make a new version of A-type objects that also have the methods in a Mixin class. For reasons that are too long to explain here, I can't use class A(Mixin), I have to use the A_factory. Below I try to give a bare bones example.
I thought naively that it would be sufficient to inherit from Mixin to endow A-type objects with the mixin methods, but the attempts below don't work:
class A: pass
class A_factory:
def __new__(self):
return A()
class Mixin:
def method(self):
print('aha!')
class A_v2(Mixin): # attempt 1
def __new__(cls):
return A_factory()
class A_v3(Mixin): # attempt 2
def __new__(cls):
self = A_factory()
super().__init__(self)
return self
In fact A_v2().method() and A_v3().method() raises AttributeError: 'A' object has no attribute 'method'.
What is the correct way of using A_factory within class A_vn(Mixin) so that A-type objects created by the factory inherit the mixin methods?
There's no obvious reason why you should need __new__ for what you're showing here. There's a nice discussion here on the subject: Why is __init__() always called after __new__()?
If you try the below it should work:
class Mixin:
def method(self):
print('aha!')
class A(Mixin):
def __init__(self):
super().__init__()
test = A()
test.method()
If you need to use a factory method, it should be a function rather than a class. There's a very good discussion of how to use factory methods here: https://realpython.com/factory-method-python/

Calling all instance methods with multiple inheritance in Python

I am trying to create a set of classes as containers of modular blocks of logic. The idea is to be able to mix and match the classes through inheritance (possibly multiple inheritance) to execute any combination of those pieces of modular logic. Here is the structure I currently have:
class Base:
methods = {}
def __init__(self):
"""
This will create an instance attribute copy of the combined dict
of all the methods in every parent class.
"""
self.methods = {}
for cls in self.__class__.__mro__:
# object is the only class that won't have a methods attribute
if not cls == object:
self.methods.update(cls.methods)
def call(self):
"""
This will execute all the methods in every parent
"""
for k,v in self.methods.items():
v(self)
class ParentA(Base):
def method1(self):
print("Parent A called")
methods = {"method":method1}
class ParentB(Base):
def method2(self):
print("Parent B called")
methods = {"method2" : method2}
class Child(ParentA, ParentB):
def method3(self):
print("Child called")
methods = {"method3" : method3}
This seems to work as expected but I was wondering if there is anything I might be missing design wise or if there is something I am trying to do that I should not be doing. Any considerations or feedback on the structure is very welcome. As well as tips on how I could make this more pythonic. Thank you all in advance.

inheriting python method with a call to super inside the method

I am developing a system, which has a series of single multilevel inheritance hierarachy. one of the methods (applicable to all the classes) has to perform the same thing for most of the classes, which is to pass a list to its parent class.
I know that if one doesn't define a method in one of the inherited classes, its parents' methods are used. But when we use the super method, we need to mention the name of the class being called.
One method I know to achieve this is to redefine the method at every class with class name as argument. Is there any elegant method where I can define it once at the topmost parent, and then override it only when necessary?
The implementation right now looks like this
class a(object):
def __init__(self):
self.myL = list()
print 'hello'
class b(a):
def __init__(self):
super(b,self).__init__()
def resolve(self, passVal):
print passVal
self.myL.append(passVal)
super(b,self).resolve(passVal+1)
class c(b):
def __init__(self):
super(c,self).__init__()
def resolve(self, passVal):
print passVal
self.myL.append(passVal)
super(c,self).resolve(passVal+1)
Instead if I can define resolve in class a, and then all other classes inherit the method from it. I understand a will never be able to use it. but redefining the method seems a lot unnecessary extra work.

Possible to return instantiator in Python?

class Parent():
def __init__(self):
self.child = Child()
class Child():
def __init__(self):
# get Parent instance
self.parent = self.Instantiator()
I know this isn't proper encapsulation but for interest's sake...
Given a "Parent" class that instantiates a "Child" object, is it possible from within Child to return the Parent object that instantiated it? And if no, I'm curious, do any languages support this?
To answer the question, no, there's no way1 the child instance knows about any classes which contain references to it. The common2 way to handle this is:
class Parent(object):
def __init__(self):
self.child = Child()
self.child._parent = self
1 Of course, this isn't strictly true. As another commentor noted, you can extract the stack frame from the executing code within the __init__ method, and examine the f_locals dictionary for the self variable for the frame before the currently executing one. But this is complicated, and prone to error. Highly unrecommended.
2 A slightly better way to handle this (depending on the specific needs of the program) might be to require the parent to pass itself to the child, like so:
class Parent(object):
def __init__(self):
self.child = Child(self)
class Child(object):
def __init__(self, parent):
self._parent = parent
Here's a reasonably-simple metaclass solution to the problem:
import functools
class MetaTrackinits(type):
being_inited = []
def __new__(cls, n, b, d):
clob = type.__new__(cls, n, b, d)
theinit = getattr(clob, '__init__')
#functools.wraps(theinit)
def __init__(self, *a, **k):
MetaTrackinits.being_inited.append(self)
try: theinit(self, *a, **k)
finally: MetaTrackinits.being_inited.pop()
setattr(clob, '__init__', __init__)
def Instantiator(self, where=-2):
return MetaTrackinits.being_inited[where]
setattr(clob, 'Instantiator', Instantiator)
return clob
__metaclass__ = MetaTrackinits
class Parent():
def __init__(self):
self.child = Child()
class Child():
def __init__(self):
self.parent = self.Instantiator()
p = Parent()
print p
print p.child.parent
a typical output, depending on the platform, will be something like
<__main__.Parent object at 0xd0750>
<__main__.Parent object at 0xd0750>
You could obtain a similar effect (in 2.6 and later) with a class decorator, but then all classes needing the functionality (both parent and children ones) would have to be explicitly decorated -- here, they just need to have the same metaclass, which may be less intrusive thanks to the "module-global __metaclass__ setting" idiom (and the fact that metaclasses, differently from class-decorations, also get inherited).
In fact, this is simple enough that I would consider allowing it in production code, if the need for that magical "instantiator" method had a proven business basis (I would never allow, in production code, a hack based on walking the stack frames!-). (BTW, the "allowing" part comes from the best-practice of mandatory code reviews: code changes don't get into the trunk of the codebase without consensus from reviewers -- this how typical open source projects work, and also how we always operate at my employer).
Here's an example based off of some of Chris B.'s suggestions to show how absolutely terrible it would be to inspect the stack:
import sys
class Child(object):
def __init__(self):
# To get the parent:
# 1. Get our current stack frame
# 2. Go back one level to our caller (the Parent() constructor).
# 3. Grab it's locals dictionary
# 4. Fetch the self instance.
# 5. Assign it to our parent property.
self.parent = sys._getframe().f_back.f_locals['self']
class Parent(object):
def __init__(self):
self.child = Child()
if __name__ == '__main__':
p = Parent()
assert(id(p) == id(p.child.parent))
Sure that'll work, but just never try to refactor it into a seperate method, or create a base class from it.
you could* try to use the traceback module, just to prove a point.
**Don't try this at home, kids*
This can be done in python with metaclasses.

Categories