Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #83763 > unrolled thread

Calling a derived class's constructor from a parent method

Started byjason <jasonsewall@gmail.com>
First post2015-01-14 08:45 -0800
Last post2015-01-15 04:44 +0000
Articles 9 — 7 participants

Back to article view | Back to comp.lang.python


Contents

  Calling a derived class's constructor from a parent method jason <jasonsewall@gmail.com> - 2015-01-14 08:45 -0800
    Re: Calling a derived class's constructor from a parent method Ian Kelly <ian.g.kelly@gmail.com> - 2015-01-14 10:00 -0700
    Re: Calling a derived class's constructor from a parent method Chris Angelico <rosuav@gmail.com> - 2015-01-15 03:56 +1100
    Re: Calling a derived class's constructor from a parent method Mark Lawrence <breamoreboy@yahoo.co.uk> - 2015-01-14 17:05 +0000
      Re: Calling a derived class's constructor from a parent method jason <jasonsewall@gmail.com> - 2015-01-14 10:10 -0800
        Re: Calling a derived class's constructor from a parent method Dave Angel <davea@davea.name> - 2015-01-14 13:41 -0500
      Re: Calling a derived class's constructor from a parent method alister <alister.nospam.ware@ntlworld.com> - 2015-01-14 18:18 +0000
    Re: Calling a derived class's constructor from a parent method Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2015-01-15 11:40 +1100
      Re: Calling a derived class's constructor from a parent method Mark Lawrence <breamoreboy@yahoo.co.uk> - 2015-01-15 04:44 +0000

#83763 — Calling a derived class's constructor from a parent method

Fromjason <jasonsewall@gmail.com>
Date2015-01-14 08:45 -0800
SubjectCalling a derived class's constructor from a parent method
Message-ID<cb109c66-090a-4779-b00e-43d964ae7252@googlegroups.com>
If I have a class hierarchy like so:

 
class A(object):
      def __init__(self, s):
            self.s = s
      def foo(self, s):
            return A(s)

class B(A):
      def __init__(self, s):
            A.__init__(self, s)

If I make a B:

b = B(0)

I'd like b.foo(1) to return an instance of B. Is there a way to do that besides implementing a construct(self, s) for each part of the hierarchy? I.e. is there a way for the base class to look at self and find out what type to create?

I'm using Python 2.7.5, but I'm curious what the 3.x answer is too.

[toc] | [next] | [standalone]


#83765

FromIan Kelly <ian.g.kelly@gmail.com>
Date2015-01-14 10:00 -0700
Message-ID<mailman.17727.1421254860.18130.python-list@python.org>
In reply to#83763
On Wed, Jan 14, 2015 at 9:45 AM, jason <jasonsewall@gmail.com> wrote:
> class A(object):
>       def __init__(self, s):
>             self.s = s
>       def foo(self, s):
>             return A(s)

Instead of explicitly naming the return class here, do this:

    return self.__class__(s)

Alternatively, since you never use self elsewhere in the method, it
may be cleaner to use a classmethod here:

    @classmethod
    def foo(cls, s):
        return cls(s)

> I'm using Python 2.7.5, but I'm curious what the 3.x answer is too.

The answer is the same in 3.x.

[toc] | [prev] | [next] | [standalone]


#83766

FromChris Angelico <rosuav@gmail.com>
Date2015-01-15 03:56 +1100
Message-ID<mailman.17728.1421255034.18130.python-list@python.org>
In reply to#83763
On Thu, Jan 15, 2015 at 3:45 AM, jason <jasonsewall@gmail.com> wrote:
> If I have a class hierarchy like so:
>
>
> class A(object):
>       def __init__(self, s):
>             self.s = s
>       def foo(self, s):
>             return A(s)
>
> class B(A):
>       def __init__(self, s):
>             A.__init__(self, s)
>
> If I make a B:
>
> b = B(0)
>
> I'd like b.foo(1) to return an instance of B. Is there a way to do that besides implementing a construct(self, s) for each part of the hierarchy? I.e. is there a way for the base class to look at self and find out what type to create?
>
> I'm using Python 2.7.5, but I'm curious what the 3.x answer is too.

Assuming you require that every subclass be able to be constructed
with that single parameter, it's not too hard. You get a 'self'
parameter; its type is the type you want to construct.

    def foo(self, s):
        return type(self)(s)

That should work just fine on either 2.7 or 3.x.

I'm not sure what this function would do in context, but this basic
technique should work.

ChrisA

[toc] | [prev] | [next] | [standalone]


#83767

FromMark Lawrence <breamoreboy@yahoo.co.uk>
Date2015-01-14 17:05 +0000
Message-ID<mailman.17729.1421255143.18130.python-list@python.org>
In reply to#83763
On 14/01/2015 16:45, jason wrote:
> If I have a class hierarchy like so:
>
>
> class A(object):
>        def __init__(self, s):
>              self.s = s
>        def foo(self, s):
>              return A(s)
>
> class B(A):
>        def __init__(self, s):
>              A.__init__(self, s)
>
> If I make a B:
>
> b = B(0)
>
> I'd like b.foo(1) to return an instance of B. Is there a way to do that besides implementing a construct(self, s) for each part of the hierarchy? I.e. is there a way for the base class to look at self and find out what type to create?
>
> I'm using Python 2.7.5, but I'm curious what the 3.x answer is too.
>

I'm confused, can you please explain what you're trying to achieve 
rather than how you're trying to achieve it and I'm sure that others 
will give better answers than I can :)

-- 
My fellow Pythonistas, ask not what our language can do for you, ask
what you can do for our language.

Mark Lawrence

[toc] | [prev] | [next] | [standalone]


#83775

Fromjason <jasonsewall@gmail.com>
Date2015-01-14 10:10 -0800
Message-ID<0fbb81a4-b37a-4428-9877-1637c5473f7f@googlegroups.com>
In reply to#83767
On Wednesday, January 14, 2015 at 12:05:55 PM UTC-5, Mark Lawrence wrote:
 
> I'm confused, can you please explain what you're trying to achieve 
> rather than how you're trying to achieve it and I'm sure that others 
> will give better answers than I can :)
> 

Good call. Coming up with a minimal example make things pretty far out of context.

The base class represents a generic function (in formal logic) with some name and a list of parameters. The derived class is some sort of specialization of that generic class (like associative functions, etc).

It is desirable to do certain things to these functions, like perform substitution or canonization, that can be implemented in the basic class but which I'd like to return as a copy rather than modify the class. Thus, the base class needs to know which derived class (if any) to create.

The burden is indeed on me to keep the signature of the init() for each of these the same. 

[toc] | [prev] | [next] | [standalone]


#83777

FromDave Angel <davea@davea.name>
Date2015-01-14 13:41 -0500
Message-ID<mailman.17733.1421260917.18130.python-list@python.org>
In reply to#83775
On 01/14/2015 01:10 PM, jason wrote:
> On Wednesday, January 14, 2015 at 12:05:55 PM UTC-5, Mark Lawrence wrote:
>
>> I'm confused, can you please explain what you're trying to achieve
>> rather than how you're trying to achieve it and I'm sure that others
>> will give better answers than I can :)
>>
>
> Good call. Coming up with a minimal example make things pretty far out of context.
>
> The base class represents a generic function (in formal logic) with some name and a list of parameters. The derived class is some sort of specialization of that generic class (like associative functions, etc).
>
> It is desirable to do certain things to these functions, like perform substitution or canonization, that can be implemented in the basic class but which I'd like to return as a copy rather than modify the class. Thus, the base class needs to know which derived class (if any) to create.
>
> The burden is indeed on me to keep the signature of the init() for each of these the same.
>

If there are additional parameters possible, you might be able to use 
*args, **vargs to pass them through the call.

-- 
DaveA

[toc] | [prev] | [next] | [standalone]


#83776

Fromalister <alister.nospam.ware@ntlworld.com>
Date2015-01-14 18:18 +0000
Message-ID<Spytw.84347$rs3.81145@fx05.am4>
In reply to#83767
On Wed, 14 Jan 2015 17:05:27 +0000, Mark Lawrence wrote:

> On 14/01/2015 16:45, jason wrote:
>> If I have a class hierarchy like so:
>>
>>
>> class A(object):
>>        def __init__(self, s):
>>              self.s = s
>>        def foo(self, s):
>>              return A(s)
>>
>> class B(A):
>>        def __init__(self, s):
>>              A.__init__(self, s)
>>
>> If I make a B:
>>
>> b = B(0)
>>
>> I'd like b.foo(1) to return an instance of B. Is there a way to do that
>> besides implementing a construct(self, s) for each part of the
>> hierarchy? I.e. is there a way for the base class to look at self and
>> find out what type to create?
>>
>> I'm using Python 2.7.5, but I'm curious what the 3.x answer is too.
>>
>>
> I'm confused, can you please explain what you're trying to achieve
> rather than how you're trying to achieve it and I'm sure that others
> will give better answers than I can :)

why not just make another b?
b2=B(1)



-- 
The computer should be doing the hard work.  That's what it's paid to do,
after all.
             -- Larry Wall in <199709012312.QAA08121@wall.org>

[toc] | [prev] | [next] | [standalone]


#83784

FromSteven D'Aprano <steve+comp.lang.python@pearwood.info>
Date2015-01-15 11:40 +1100
Message-ID<54b70c8c$0$12999$c3e8da3$5496439d@news.astraweb.com>
In reply to#83763
jason wrote:

> If I have a class hierarchy like so:
> 
>  
> class A(object):
>       def __init__(self, s):
>             self.s = s
>       def foo(self, s):
>             return A(s)

A.foo is broken, or at least rude.  Change it to this:

    def foo(self, s):
        return type(self)(s)



> class B(A):
>       def __init__(self, s):
>             A.__init__(self, s)

Unrelated:

It is better to call super than manually call the superclass. Calling A
directly means your class is no longer compatible with multiple
inheritance.

    def __init__(self, s):
        super(B, self).__init__(s)


> I'm using Python 2.7.5, but I'm curious what the 3.x answer is too.


The answer in 3.x is the same, except that super() can auto-detect the right
arguments:

        super().__init__(s)



-- 
Steven

[toc] | [prev] | [next] | [standalone]


#83789

FromMark Lawrence <breamoreboy@yahoo.co.uk>
Date2015-01-15 04:44 +0000
Message-ID<mailman.17738.1421297070.18130.python-list@python.org>
In reply to#83784
On 15/01/2015 00:40, Steven D'Aprano wrote:
> jason wrote:
>
>> class B(A):
>>        def __init__(self, s):
>>              A.__init__(self, s)
>
> Unrelated:
>
> It is better to call super than manually call the superclass. Calling A
> directly means your class is no longer compatible with multiple
> inheritance.
>
>      def __init__(self, s):
>          super(B, self).__init__(s)
>

For the OP an excellent article on super here 
https://rhettinger.wordpress.com/2011/05/26/super-considered-super/

-- 
My fellow Pythonistas, ask not what our language can do for you, ask
what you can do for our language.

Mark Lawrence

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.python


csiph-web