class base():
def __init__(self):
self.var = 10
def add(self, num):
res = self.var+num
return res
class inherit(base):
def __init__(self, num=10):
x = super().add(num)
a = inherit()
print(a)
Hello,
I'm learning about inheritance and super(). When running this, the error AttributeError: 'inherit' object has no attribute 'var' is returned. How can I inherit the init variables too?
You first need to call super constructor because you did not define var in your base class constructor.
Working version of your code (though you should probably add var in base __init__)
class Base:
def __init__(self):
self.var = 10
def add(self, num):
res = self.var + num
return res
class Inherit(Base):
def __init__(self, num=10):
super().__init__()
x = super().add(num)
a = Inherit()
print(a)
one possible solution
class Base:
def __init__(self, var=10):
self.var = var
def add(self, num):
res = self.var + num
return res
class Inherit(Base):
pass
a = Inherit()
a.add(0) # replace 0 with any integer
Related
I'm playing around with class inheritance and I'm wondering if its possible to change aspects of an inherited method in the child class without having to rewrite the whole thing?
For example:
class Parent:
def _init_(self, x):
self.x = x
def foo(self):
a = self.x
if a > 0:
forward = True
elif a < 0:
forward = False
return forward
class Child1(Parent):
def foo(self, y=None, bool=False):
if bool:
a = y
else:
a = self.x
super().foo()
class Child2(Parent):
pass
What I'm looking for is if I called Child1.foo it could reassign the variable a before running through
the method, as defined in the parent class. Where a is dependent on the y and bool arguments passed through the rewritten method in Child1:
print(Child1(2).foo(-2, True))
# => False
print(Child1(2).foo())
# => True
print(Child2(2).foo())
# => True
Is this possible, or would I just have to rewrite a new method for each class?
I think I understand your problem and I have some suggestions for how you can resolve this:
Using "private" methods
For example:
class Parent:
def __init__(self, x):
self.x = x
def _foo(self, a=None):
a = a if a else self.x * 2
if a > 10:
over = True
else:
over = False
return over
def foo(self):
return self._foo()
class Child1(Parent):
def foo(self, y=None, condition=False):
if condition:
a = y*2
else:
a = self.x*2
return self._foo(a)
class Child2(Parent):
pass
In this example, all child classes will inherit the _foo "private" function, where they may or may not receive a value of a.
Using abstract classes
There is another solution to this problem with abstract classes (here is an example of how to do this), where you forces the child class to implement the function foo:
Important
Remembering that in the case of abstract classes, if you do not define the function decorated with #abstractmethod, you will receive an error similar to this TypeError: Can't instantiate abstract class Child2 with abstract methods foo
Example:
Python 2.x
from abc import ABCMeta, abstractmethod
class Parent:
__metaclass__ = ABCMeta
def __init__(self, x):
self.x = x
def _foo(self, a=None):
a = a if a else self.x * 2
if a > 10:
over = True
else:
over = False
return over
#abc.abstractmethod
def foo(self):
pass
class Child1(Parent):
def foo(self, y=None, condition=False):
if condition:
a = y*2
else:
a = self.x*2
return self._foo(a)
class Child2(Parent):
def foo(self):
return self._foo()
Python 3.x
class Parent(metaclass=ABCMeta):
def __init__(self, x):
self.x = x
def _foo(self, a=None):
a = a if a else self.x * 2
if a > 10:
over = True
else:
over = False
return over
#abc.abstractmethod
def foo(self):
pass
class Child1(Parent):
def foo(self, y=None, condition=False):
if condition:
a = y*2
else:
a = self.x*2
return self._foo(a)
class Child2(Parent):
def foo(self):
return self._foo()
In both examples you will have the same result by running this:
print(Child1(2).foo(10, True)) // True
print(Child1(2).foo()) // False
print(Child2(2).foo()) // False
For example, if I have two classes :
class A:
def __init__(self):
self.a = 1;
def update(self, val):
self.a = val;
class B:
def __init__(self, default = A()):
self.b = default.a;
Using them :
object_a = A(); object_b = B(object_a);
Then, I would like to update the object_a.a attribute using object_a.update(update_val) but also concurrently update at all other dependent objects (object_b.b will also be updated to update_val).
How to do this in Python, is there a 'built-in' way?
I already have some manual solutions in mind, such as:
class A:
def __init__(self):
self.a = 1;
self.dependent = None;
def update(self, val):
self.a = val;
if self.dependent != None:
self.dependent.b = self.a;
class B:
def __init__(self, default = A()):
default.dependent = self;
self.b = default.a;
One way to accomplish what you are asking is use a mutable object, such as a list, to store the attribute's data. Since the objects will reference the list, changing the values of the list will be shared to both objects.
Here is a version that uses a list to store the underlying value, but maintains the attribute behavior .a and .b
class A:
def __init__(self):
self._a = [1]
def update(self, val):
self._a[0] = val
#property
def a(self):
return self._a[0]
class B:
def __init__(self, default):
self._b = default._a
#property
def b(self):
return self._b[0]
a = A()
b = B(a)
a.update(4)
b.b
# returns:
4
I am creating a subclass, but I am having difficulties making it inherit from the parent class:
def ParentClass(object):
def __init__(self,num):
self.num = num
self.get_soup()
def get_soup(self):
self.soup = 'soup'
return self.soup
def SubClass(Advert):
def __init__(self,num):
ParentClass.__init__(self,num)
def test(self):
print 'it works'
print self.num
if __name__== "__main__":
num = 1118868465
ad = SubClass(num)
ad.test()
Should I have a look at metaclasses?
You have functions in your code not classes, the parent class is also called ParentClass not Advert:
class ParentClass(object): # class not def
def __init__(self,num):
self.num = num
self.get_soup()
def get_soup(self):
self.soup = 'soup'
return self.soup
class SubClass(ParentClass): # inherit from ParentClass
def __init__(self, num):
super(SubClass, self).__init__(num)
def test(self):
print 'it works'
print self.num
You might want to have a read of this tutorial
Say I have a class "NumberStore"
class NumberStore(object):
def __init__(self, num):
self.num = num
def get(self):
return self.num
And later on, for the purpose of serialization, I want to print a definition of the class, either exactly as stated, or equivalently stated. Is there any way in python to access a class's definition as in the idealized example below?
>>> NumberStore.print_class_definition()
"class NumberStore(object):\n def __init__(self, num):\n self.num = num\n \n def get(self):\n return self.num"
Yep, with inspect.getsource:
from inspect import getsource
class NumberStore(object):
def __init__(self, num):
self.num = num
def get(self):
return self.num
#classmethod
def print_class_definition(cls):
return getsource(cls)
Use inspect.getsource.
import inspect
source_text = inspect.getsource(NumberStore)
I have two classes. a and b.
In one of class a's methods, I created an object of class b. One of class b attributes takes a function. So say I gave it a random function but does this function of class b have access to class a's attribute? even though I didn't pass it in directly as a parameter?
class b:
def __init__(self):
self.attribute_function = None
class a:
def __init__(self):
self.temp = 10
self.counter = 0
def temp(self):
obj = b()
obj.attribute_function = lambda self: self.counter < self.temp
return obj.attribute_function()
if __name__ == "__main__":
#pass
obj = a()
print obj.temp()
In the above example, I tried to provide a really basic example, but if you run it, it doesn't work...
Revised Code, class a should look like this:
class a:
def __init__(self):
self.temp = 10
self.counter = 0
def temp(self):
obj = b()
obj.attribute_function = lambda args: self.counter < self.temp
return obj.attribute_function(1) # i added this 1 to fill in arg
This works:
class b:
def __init__(self):
self.attribute_function = None
class a:
def __init__(self):
self._temp = 10
self.counter = 0
def temp(self):
obj = b()
obj.attribute_function = lambda self=self: self.counter < self._temp
return obj.attribute_function()
if __name__ == "__main__":
obj = a()
print obj.temp()
On problem you had is self.temp = 10 which shadowed your method temp().
Another problem: lambda self: self.counter < self._temp. Your lambda function was expecting an argument. But omitting self is not a good idea lambda : self.counter < self._temp, because if you call obj.attribute_function() somewhere where self is not available or has changed - it will not find self or use another self. self=self fixes that.
But generally such magic is an anti-pattern. Tell us what are your trying to achieve, and there should be a better way to do what you want. Otherwise this kind of code will ensure many headaches.
I think this is a better solution (called strategy pattern):
class B:
def __init__(self, a):
self.a = a
def temp(self):
return self.a.temp()
class A:
def __init__(self):
self._temp = 10
self.counter = 0
def temp(self):
return self.counter < self._temp
if __name__ == "__main__":
obj = B(A())
print obj.temp()
Your example does not work because you have a name collision at temp
You have assigned temp to be both a method:
def temp(self):
and an attribute:
self.temp = 10