How to make one instance of a derived class share attributes and state with another instance of its base class in Python?
class Foo(object):
def __init__(self, a, b):
self.value = a
def method1(self):
self.value += 1
return self.value
class Foo_child(Foo):
def __init__(self, Foo_instance, c, d):
super().__init__()
A = Foo(30,40)
B = Foo_child(A,50,60)
What i need is some way where changing B should affect A and vice versa.
For e.g. If i call B.method1, then i need A to have a A.value of 31 and vice versa. Is there any obvious pythonic way to do this?
Your problem is a containment (has-a) relationship, not a is-a relationship. It may also be necessary to make Foo_child inherit from Foo (they provide the same functionality), but in essence you want to delegate handling of value and method1 to Foo_instance.
Re-implement method1 on Foo_child to delegate to Foo_instance, value on Foo_child should be a property object that also delegates:
class Foo_child(Foo):
def __init__(self, Foo_instance, c, d):
super().__init__(c, d)
self.Foo_instance = Foo_instance
#property
def value(self):
return self.Foo_instance.value
#value.setter
def value(self, value):
self.Foo_instance.value = value
def method1(self):
return self.Foo_instance.method1()
Related
When working with python instances, it is possible to access bound methods of the same class using self. This resolves to a method corresponding to the same class in hierarchy.
class A:
def f(self):
return 1
def __init__(self):
self.v = self.f()
class B(A):
def f(self):
return 2
b = B()
# b.v is set to 2
But, when working with class methods, there is no apparent way of accessing methods of the same class as above.
In my use case, f above needs to be a class method and I need to set class variable v according to f corresponding to the same class. Somewhat like:
class A:
#classmethod
def f(cls):
return 1
v = resolution_of_calling_class.f()
class B(A):
#classmethod
def f(cls):
return 2
# B.v should be 2
edit: v is actually an attribute defined by parent class, which should find a method overridden by child class
You just need to override __new__ method, since it is invoked before the __init__ and its purpose is to create an instance, that will be initialized by __init__.
class A:
def __new__(cls, *args, **kwargs):
cls.v = cls.f()
return super().__new__(cls, *args, **kwargs)
#classmethod
def f(cls):
return 1
class B(A):
#classmethod
def f(cls):
return 2
a = A()
print(a.v)
b = B()
print(b.v)
1
2
I am not 100% sure I understand what you are trying to do.
I used your code above and
class A:
#classmethod
def f(cls):
return 1
class B:
#classmethod
def f(cls):
return 2
print(B.f())
gives me 2 just as I expected it would. Should B be a child class of A as in the first example?
I have a class that inherits from two others and I want to get the return of the method called "render" that both have this method
ex:
class A:
def render(self, value, name):
return 'render A'
class B:
def render(self, value, name):
return 'render B'
class C(B, A):
def render(self, value, name):
render_a = #here get the value of A
render_b = #here get the value of B
return render_a
You probably should here specify the classes explictily. You can take a look at the direct base classes, or look at the entire MRO, but then you will need to specify what to do if later another direct (or indirect) superclass is added. You thus can call it with A.render(self, value, name):
class C(B, A):
def render(self, value, name):
render_a = A.render(self, value, name)
render_b = B.render(self, value, name)
return render_a
Let's say I have a class called Adder:
class adder(object):
def __init__(self, a, b):
self.a=a
self.b=b
self.result = None
def perform_addition(self):
self.result = self.a + self.b
return self.result
If I instantiate this class:
myAdder = adder(1,2)
Then the value of myAdder.result depends on calling perform_addition() first, otherwise it'll always remain None. It other words, there's a dependency on perform_addition() for the value of self.result. And if we extrapolate, a more complex class can have a chain of dependencies: ie, you have to call functions A, B, and C before D, because they in turn populate the necessary variables that the next function needs.
Is this bad class design? What is the remedy for it?
I think the above is a example of: https://en.wikipedia.org/wiki/Sequential_coupling
I think it all depends on what you want to do and how you want to go about it. the code you have is not necessarily bad, if you want a static dependency on 'perform_addition()' for the value of 'self.result' . But if you want a dynamic dependency, then the code below will be a good and simple approach. this way when an object is created by instantiating the class with values 'a' and 'b', 'self.result' will be automatically computed. you could also use more advanced tools like properties, decorators, descriptors etc. like i said, it all depends on what you want.
Class adder(object):
def __init__(self, a, b):
self.a=a
self.b=b
self.result = self.perform_addition()
def perform_addition(self):
self.result = self.a + self.b
return self.result
This would be a good case to make result a property instead, so that the addition is only performed when the result attribute is accessed:
class adder(object):
def __init__(self, a, b):
self.a = a
self.b = b
#property
def result(self):
return self.a + self.b
myAdder = adder(1,2)
print(myAdder.result)
This outputs: 3
In case the result attribute is expected to be accessed multiple times and that the calculation involved is expensive, you can save the result in an instance variable to avoid re-calculations:
class adder(object):
def __init__(self, a, b):
self.a = a
self.b = b
self._result = None
#property
def result(self):
if self._result is None:
self._result = self.a + self.b
return self._result
I am trying to subclass a python class and overwrite a regular attribute with a #property function. The catch is that I can't modify the parent class, and the api for the child class needs to look the same as the parent class (but behave differently). (So my question is different from this one in which the parent class also used a #property method to access the underlying attribute.)
The simplest possible example is
# assume this class can't be overwritten
class Parent(object):
def __init__(self, a):
self.attr = a
# how do I make this work?
class Child(Parent):
def __init__(self, a):
super(Child, self).__init__(a)
# overwrite access to attr with a function
#property
def attr(self):
return super(Child, self).attr**2
c = Child(4)
print c.attr # should be 16
This produces an error when the parent init method is called.
<ipython-input-15-356fb0400868> in __init__(self, a)
2 class Parent(object):
3 def __init__(self, a):
----> 4 self.attr = a
5
6 # how do I make this work?
AttributeError: can't set attribute
Hopefully it is clear what I want to do and why. But I can't figure out how.
This is easily fixed by adding a setter method
class Child(Parent):
def __init__(self, a):
self._attr = None
super(Child, self).__init__(a)
# overwrite access to a with a function
#property
def attr(self):
return self._attr**2
#attr.setter
def attr(self, value):
self._attr = value
I have a class where I need access to a computed value that can only be calculated per subclass.
This computation is not cheap, and since there are many instantiations of the subclasses, I want to compute this value only once per subclass.
I can think of two solution which I don't really like:
Either the parent class will have a #classmethod start() which will compute the values.
this enforces me to identify the precise location of the first instantiation of each class, so I've ruled this option out.
or, this code:
class A(object):
#classmethod
def _set_cls_attribute(cls):
if hasattr(cls, 'big_attr'):
return
cls.big_attr = heavy_func(cls.VAL)
def __init__(self):
self._set_cls_attribute()
class B(A):
VAL = 'b'
class C(A):
VAL = 'c'
for _ in range(large_number):
b = B()
c = C()
I don't like using hasattr though...
Is there anything better?
A metaclass is a handy way to solve this
class A_meta(type):
def __init__(cls, *args):
type.__init__(cls, *args)
if hasattr(cls, 'VAL'):
cls.big_attr = heavy_func(cls.VAL)
class A(object):
__metaclass__ = A_meta
class B(A):
VAL = 'b'
class C(A):
VAL = 'c'
Another way along the same lines as yours. This has the advantage of deferring the call to heavy_func until the attribute is first accessed.
class A(object):
def __getattr__(self, attr):
if attr == 'big_attr':
self.__class__.big_attr = heavy_func(self.VAL)
return object.__getattribute__(self, attr)
Without metaclasses or hasattr :
class A(object):
#classmethod
def attribute(cls):
v = heavy_func(cls.VAL)
cls.attribute = lambda k : v
return v