1

How can I define a subclass using an instance of the superclass without typing a lot? See:

class A():
    def __init__(self,x,y):
        self.x=x
        self.y=y

class B(A):
    def __init__(self,x,y,z):
        A.__init__(A,x,y)
        self.z=z

class1=A(2,3)
class2=B(class1.x,class1.y,5)   # Is there something easier than this, where I don't have to type class1.x, class1.y and
                                # I can just pass all the data members of class1 at once?
l7ll7
  • 1,309
  • 1
  • 10
  • 20
  • Um, `class2=B(2,3,5)`? – juanpa.arrivillaga Dec 24 '17 at 06:41
  • That doesn't seem like much (needless) typing.. if there is x,y,z..foobar,quxx, that might indicate a use of sequences or such.. there is also kwargs that is sometimes used as a pass-through (at the expense of clarity and directly bound parameters), but it seems fine how it is. – user2864740 Dec 24 '17 at 06:45
  • For this specific example, you could pass an instance of `A` to `B.__init__()` . – John Gordon Dec 24 '17 at 07:03
  • @juanpa.arrivillaga That will work only in this MWE. Imagine my class has *a lot* of data attributes that may change: I need a more general solution, where I can pass all of them directly, automatically, without typing too much. – l7ll7 Dec 24 '17 at 10:45
  • @user2864740 your kwargs solution may work. How would that look in practice? Ideally I'd want something that looks syntactically like `class2= B(class1., 5)` – l7ll7 Dec 24 '17 at 10:46
  • @JohnGordon I'm not sure, how do you mean that? Isn't that very similar to my way of obtaining an instance of `B`? – l7ll7 Dec 24 '17 at 10:49
  • @nicht `class2=B(class1, 5)` – John Gordon Dec 24 '17 at 16:34
  • @JohnGordon Tried that but it gives an error: positional argument `z` missing – l7ll7 Dec 24 '17 at 20:08
  • 1
    @nicht You'd also have to change the init function to take different arguments. See my answer below. – John Gordon Dec 24 '17 at 20:16

1 Answers1

0
class A(object):
    def __init__(self,x,y):
        self.x=x
        self.y=y

class B(A):
    def __init__(self,a,z):
        self.a=a
        self.z=z

class1=A(2,3)
class2=B(class1,5)
John Gordon
  • 29,573
  • 7
  • 33
  • 58
  • This is *quasi* composition, not inheritance and it *breaks* methods A called upon B which exect `x` and `y` properties. It would be less confusing (ie. full composition) if class B *did not* extend A, especially since the initializer for A is never called. – user2864740 Dec 25 '17 at 00:32
  • Methods in B would have to be modified to use self.a.x instead of self.x. – John Gordon Dec 26 '17 at 04:38
  • Am I missing something? The initializer for A certainly _is_ called: `class1=A(2,3)` – John Gordon Dec 26 '17 at 04:38
  • It's called for the *A instance*, not the *B instance* which is (incorrectly) a subtype of A. This is why it's *quasi* (as in, not correct) composition .. – user2864740 Dec 26 '17 at 05:09
  • Ah, I see your point. Instances of A will expect `self.x` and `self.y` to exist, but instances of B (which are also instances of A) won't have those attributes. B should not inherit from A, as you said. – John Gordon Dec 26 '17 at 05:19
  • @JohnGordon I'm confused by the remarks below this answer (I cannot really understand what the issue is): Does that mean that this approach is better avoided in case my classes include many more methods and other things? – l7ll7 Dec 30 '17 at 15:18
  • @nicht This answer is wrong. Don't do it this way. – John Gordon Dec 30 '17 at 17:19