问题
I am not quite used to class inheritance in Python yet. All I want to do is simply pass all arguments from my base class to the super class when it is created:
class A:
def __init__(self, a, b):
self.a = a
self.b = b
def do(self):
c = self.a + self.b
return B(c=c)
class B(A):
def __init__(self, c):
self.c = c
my_A = A(a=1, b=2)
my_B = my_A.do()
print(my_B.c)
This works as expected. However, what I want is to also be able to call the arguments a and b from the x2 instance of the class my_B, so that I can directly write my_B.a for instance. I know this is done with super() like this:
class A:
def __init__(self, a, b):
self.a = a
self.b = b
def do(self):
c = self.a + self.b
return B(a=self.a, b=self.b, c=c)
class B(A):
def __init__(self, a, b, c):
super(B, self).__init__(a=a, b=b)
self.c = c
my_A = A(a=1, b=2)
my_B = my_A.do()
print(my_B.a)
print(my_B.b)
However, I don't want to explicitly write all arguments of A when I create the instance of B. Is there a way to automatically pass all arguments from class A to class B?
回答1:
Based on your comment, you could do something like this:
class B(A):
def __init__(self, c, an_a):
super(B, self).__init__(an_a.a, an_a.b)
self.c = c
You may instead prefer to keep your current constructor and add a from_a static method:
class B(A):
def __init__(self, c, a, b): # note order
super(B, self).__init__(a=a, b=b)
self.c = c
@staticmethod
def from_a(c, an_a):
return B(c, an_a.a, an_a.b)
Finally, if you don't want to type out all of those parameters, you can add an args() method to A and then use the collection unpacking function syntax:
class A:
...
def args(self):
return (self.a, self.b)
class B(A):
def __init__(self, c, *args): # Note *args
super(B, self).__init__(*args)
self.c = c
@staticmethod
def from_a(c, an_a):
return B(c, *an_a.args())
Now B's constructor takes the parameter special to B, followed by any number of parameters which just get passed to A's constructor. This allows you to do the tuple unpacking when calling the constructor, instead of listing everything out manually.
回答2:
Ok, thanks for your comments. I have come up with this solution:
class A:
def __init__(self, a, b):
self.a = a
self.b = b
def do(self):
c = self.a + self.b
return B(self, c)
class B:
def __init__(self, base, c):
self.base = base
self.c = c
my_A = A(a=1, b=2)
my_B = my_A.do()
print(my_B.base.a)
print(my_B.base.b)
print(my_B.c)
This removes the inheritance of class B and makes the code slightly less readable, but I guess it will do, right? 😊
回答3:
yup there is a way use key word arguments so :
class A(object):
def __init__(self,**kwargs):
# Non pythonic and a bit of a hack
self.kwargs = kwargs
vars(self).update(kwargs)
def do(self):
c = self.a + self.b
return B(c=c, **kwargs)
class B(A):
def __init__(self, c, **kwargs):
self.c = c
super(B, self).__init__(**kwargs)
my_A = A(a=1, b=2)
my_B = my_A.do()
print(my_B.a)
print(my_B.b)
print(my_B.c)
This does what you are after nonethless the way in which it was written before was a bit more pythonic when run this should output:
1
2
3
The downside of doing this is that now A has not limit in terms of the number of attributes but you could ensure this with an assertion or something I guess.
来源:https://stackoverflow.com/questions/32185528/python-inheritance-pass-all-arguments-from-base-to-super-class