Consider the following code:
class A:
def foo(self, a):
return a
def bar(self, a):
print(foo(a))
class B(A):
def foo(self, a):
return a[0]
Now calling B.bar(a) the result is print(a[0]), but what I want is print(a). More directly: I'd like that the calling of bar()in a child class uses the definition of foogiven in A even if overridden. How do i do that?
I believe this is what you are looking for:
class A(object):
def foo(self, a):
return a
def bar(self, a):
print(A.foo(self,a))
class B(A):
def foo(self, a):
return a[0]
or alternatively:
class A:
def foo(self, a):
return a
def bar(self, a):
print(self.foo(a))
class B(A):
def foo(self, a):
return super().foo(a)
Related
I am importing several classes from a library with a common method, like
class BarClass1:
def __init__(self):
pass
def bar(self, x):
return x + 1
class BarClass2:
def __init__(self):
pass
def bar(self, x):
return x + 2
class BarClass3:
def __init__(self):
pass
def bar(self, x):
return x + 3
I want to add logging to the bar method of each class, and for that purpose I create children for these classes in the following way:
def log_something(x):
print(f'input is {x}')
class DerivedBarClass1(BarClass1):
def __init__(self):
super().__init__()
def bar(self, x):
log_something(x)
return super().bar()
class DerivedBarClass2(BarClass2):
def __init__(self):
super().__init__()
def bar(self, x):
log_something(x)
return super().bar()
class DerivedBarClass3(BarClass3):
def __init__(self):
super().__init__()
def bar(self, x):
log_something(x)
return super().bar()
I feel I am doing a lot of code repetition, is there a simpler way of doing this? My main constraint is not being able to modify the code in BarClass1, BarClass2 or BarClass3.
If you can't modify the code, you can always monkey-patch the classes...
import functools
def add_logging_single_arg(f): # maybe a better name...
#functools.wraps(f)
def wrapper(self, x):
log_something(x)
return f(x)
return wrapper
for klass in [BarClass1, BarClass2, BarClass3]:
klass.bar = add_logging_single_arg(bar)
In the following example
class A():
def __init__(self):
self.foo = 'foo'
class B():
def __init__(self, a):
self.a = a
a = A()
B(a) # right
B('a') # wrong
I want to do something like B.__init__(self, a:A) so that the argument in class B is an object of A.
You can always raise a ValueError:
class B():
def __init__(self, a: A):
if not isinstance(a, A):
raise ValueError("a must an object of class A")
self.a = a
class A(object):
__A = None
def get_a(self):
return self.__A
def set_a(self, value):
self.__A = value
class B(A):
def method_b(self, value):
self.set_a(value)
class C(A):
def method_c(self)
self.get_a()
Someone can to explain me how can i to catch installed value in method_b inside my 'C' class method?
P.S. In this variant i just getting nothing.
Python isn't Java; you don't need setters & getters here: just access the attributes directly.
There are three problems with your code.
C.method_c() has no return statement, so it returns None.
You are using __ name mangling when that's exactly what you don't want.
In A.set_a() you want to set a class attribute, but your assignment instead creates an instance attribute which shadows the class attribute.
Here's a repaired version.
class A(object):
_A = 'nothing'
def get_a(self):
return self._A
def set_a(self, value):
A._A = value
class B(A):
def method_b(self, value):
self.set_a(value)
class C(A):
def method_c(self):
return self.get_a()
b = B()
c = C()
print(c.method_c())
b.method_b(13)
print(c.method_c())
output
nothing
13
Here's a slightly more Pythonic version:
class A(object):
_A = 'nothing'
class B(A):
def method_b(self, value):
A._A = value
class C(A):
pass
b = B()
c = C()
print(c._A)
b.method_b(13)
print(c._A)
I have following piece of code in Python. There are two classes A2 and B2 which share functions f1() and f2(). They differ in their base classes, deriving from A and B respectively.
I can see how to generalize this in C++ using templates. But I am not sure how to do this Python.
class A2(A):
def __init__(self):
A.__init__(self)
self._Z = Z('high')
def f1(self):
return self._Z.f1()
def f2(self):
return self._Z.f2()
# ... more functions ...
class B2(B):
def __init__(self):
B.__init__(self)
self._Z = Z('low')
def f1(self):
return self._Z.f1()
def f2(self):
return self._Z.f2()
# ... more functions ...
If I understand your question, you might try a mixin class:
class Mixin(object):
def f1(self):
return self._Z.f1()
def f2(self):
return self._Z.f2()
class A2(A, Mixin):
def __init__(self):
A.__init__(self)
self._Z = Z('high')
class B2(B, Mixin):
def __init__(self):
B.__init__(self)
self._Z = Z('low')
I'm currently using this pattern to create a class C that inherits from A and B. I couldn't call super().__init__ from C since I would have to do the same in A and B, and the unexpected parameter would cause problems at the top level. I feel like this isn't very elegant. What is the proper way to do multiple inheritance in Python? I guess it is unusual to query the mro to find out if the superclass expects a parameter?
class A:
def __init__(self, something):
self.a = X(something)
def method_a(self):
self.a.go()
def method_ab(self):
self.a.go2()
class B:
def __init__(self, something):
self.b = X(something)
def method_b(self):
self.b.go()
def method_ab(self):
self.b.go2()
class C(A, B):
def __init__(self, something):
self.a_ = A(something)
self.b_ = B(something)
#property
def a(self):
return self.a_.a
#property
def b(self):
return self.b_.b
def method_ab(self):
for x in [self.a, self.b]:
x.method_ab()
The best solution I found was to use a base class to absorb the extra parameters:
class Base:
def __init__(self, something):
pass
def method_ab(self):
pass
class A(Base):
def __init__(self, something):
super().__init__(something)
self.a = X(something)
def method_a(self):
self.a.go()
def method_ab(self):
super().method_ab()
self.a.go()
class B(Base):
def __init__(self, something):
super().__init__(something)
self.b = X(something)
def method_b(self):
self.b.go()
def method_ab(self):
super().method_ab()
self.b.go()
class C(A, B):
pass