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


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

Is this the proper way to use a class method?

Started byJohn Salerno <johnjsal@gmail.com>
First post2012-03-01 22:00 -0800
Last post2012-03-01 23:16 -0800
Articles 8 — 3 participants

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


Contents

  Is this the proper way to use a class method? John Salerno <johnjsal@gmail.com> - 2012-03-01 22:00 -0800
    Re: Is this the proper way to use a class method? Chris Rebert <clp2@rebertia.com> - 2012-03-01 22:25 -0800
      Re: Is this the proper way to use a class method? John Salerno <johnjsal@gmail.com> - 2012-03-01 23:16 -0800
        Re: Is this the proper way to use a class method? Ian Kelly <ian.g.kelly@gmail.com> - 2012-03-02 01:04 -0700
        Re: Is this the proper way to use a class method? Chris Rebert <clp2@rebertia.com> - 2012-03-02 00:08 -0800
          Re: Is this the proper way to use a class method? John Salerno <johnjsal@gmail.com> - 2012-03-02 10:51 -0800
          Re: Is this the proper way to use a class method? John Salerno <johnjsal@gmail.com> - 2012-03-02 10:51 -0800
      Re: Is this the proper way to use a class method? John Salerno <johnjsal@gmail.com> - 2012-03-01 23:16 -0800

#21121 — Is this the proper way to use a class method?

FromJohn Salerno <johnjsal@gmail.com>
Date2012-03-01 22:00 -0800
SubjectIs this the proper way to use a class method?
Message-ID<4136337.363.1330668021961.JavaMail.geo-discussion-forums@ynjd19>
This is purely for fun and learning, so I know there are probably better ways of creating a chess program. Right now I'm just curious about my specific question, but I'd love to hear any other advice as well.

Basically, I'm wondering if I'm using the class method properly with the move method. The reason I did it this way is because every chess piece will obviously have its own move method, yet they will all need to mark the piece as moved, so I figure that's best written once in the superclass.

This works, but doing it this way seems weird, since the point of a class method is that it can be called by the class itself, even before instances have been created. Yet the way I've implemented it, it is necessarily tied to being called on an instance. Is this wrong? Is there a better way to do what I'm doing with move?

Also, do I need the @classmethod decorator? The book I'm reading says to use it (and @staticmethod), but the following code works without it.

Thanks.



class ChessPiece:

    def __init__(self, position, label, has_moved):
        try:
            self.position = (position[0], int(position[1]))
        except TypeError:
            self.position = position
        self.label = label
        self.has_moved = has_moved

    def move(cls, self):
        self.has_moved = True


class Pawn(ChessPiece):

    def __init__(self, position=None, label=1, has_moved=False):
        super().__init__(position, label, has_moved)

    def move(self):
        super().move(self)
        self.position = (chr(ord(self.position[0]) + 1), self.position[1] + 1)
            

[toc] | [next] | [standalone]


#21122

FromChris Rebert <clp2@rebertia.com>
Date2012-03-01 22:25 -0800
Message-ID<mailman.339.1330669514.3037.python-list@python.org>
In reply to#21121
On Thu, Mar 1, 2012 at 10:00 PM, John Salerno <johnjsal@gmail.com> wrote:
> This is purely for fun and learning, so I know there are probably better ways of creating a chess program. Right now I'm just curious about my specific question, but I'd love to hear any other advice as well.
>
> Basically, I'm wondering if I'm using the class method properly with the move method.

Unfortunately, no.

> The reason I did it this way is because every chess piece will obviously have its own move method, yet they will all need to mark the piece as moved, so I figure that's best written once in the superclass.

Right, but why not just a regular instance method? The method in
question doesn't operate upon *the class itself* at all (which is the
raison d'etre of classmethods); it instead operates upon an instance.
A staticmethod would be slightly less weird, but really, it should
just be an instance method.

> This works, but doing it this way seems weird, since the point of a class method is that it can be called by the class itself, even before instances have been created. Yet the way I've implemented it, it is necessarily tied to being called on an instance. Is this wrong? Is there a better way to do what I'm doing with move?

Just make it a normal instance method (i.e. remove the `cls` argument).

> Also, do I need the @classmethod decorator? The book I'm reading says to use it (and @staticmethod), but the following code works without it.

That's just a coincidence. Your supercall is ought to be: super().move()
In contrast, super().move(self) calls the superclass instance method
`move` with 2 arguments, both `self`, which just happens to work given
your move() method, inside which `cls` isn't actually a class like it
ought to be.

<snip>
> class ChessPiece:
>
>    def __init__(self, position, label, has_moved):
>        try:
>            self.position = (position[0], int(position[1]))
>        except TypeError:
>            self.position = position
>        self.label = label
>        self.has_moved = has_moved
>
>    def move(cls, self):
>        self.has_moved = True
>
>
> class Pawn(ChessPiece):
>
>    def __init__(self, position=None, label=1, has_moved=False):
>        super().__init__(position, label, has_moved)
>
>    def move(self):
>        super().move(self)
>        self.position = (chr(ord(self.position[0]) + 1), self.position[1] + 1)

Cheers,
Chris

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


#21125

FromJohn Salerno <johnjsal@gmail.com>
Date2012-03-01 23:16 -0800
Message-ID<21646224.4.1330672614560.JavaMail.geo-discussion-forums@ynt13>
In reply to#21122
> That's just a coincidence. Your supercall is ought to be: super().move()
> In contrast, super().move(self) calls the superclass instance method
> `move` with 2 arguments, both `self`, which just happens to work given
> your move() method, inside which `cls` isn't actually a class like it
> ought to be.

Thank you! This is the whole reason I tried using a class method in the first place. I was getting an error that said my move method only takes one argument, but I was passing in two.

But if I make the super call as super().move(), how does that work? The move method in the superclass takes an argument, and if I just do super().move(), isn't it the subclass that's getting passed to it? How does the superclass move method know what 'self' is if it doesn't get passed to it as I did originally?

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


#21130

FromIan Kelly <ian.g.kelly@gmail.com>
Date2012-03-02 01:04 -0700
Message-ID<mailman.344.1330675495.3037.python-list@python.org>
In reply to#21125
On Fri, Mar 2, 2012 at 12:16 AM, John Salerno <johnjsal@gmail.com> wrote:
>> That's just a coincidence. Your supercall is ought to be: super().move()
>> In contrast, super().move(self) calls the superclass instance method
>> `move` with 2 arguments, both `self`, which just happens to work given
>> your move() method, inside which `cls` isn't actually a class like it
>> ought to be.
>
> Thank you! This is the whole reason I tried using a class method in the first place. I was getting an error that said my move method only takes one argument, but I was passing in two.
>
> But if I make the super call as super().move(), how does that work? The move method in the superclass takes an argument, and if I just do super().move(), isn't it the subclass that's getting passed to it?

The self that gets passed into the superclass.move() or the
subclass.move() is the exact same object in either case.  There is no
"up-casting" (or any casting at all, for that matter) in Python.

> How does the superclass move method know what 'self' is if it doesn't get passed to it as I did originally?

super() called without arguments is equivalent to super(<class this
method was defined in>, self) -- it collects the value of self from
the current stack frame.  So self is able to be passed in because the
super object implicitly knows what self is.

Cheers,
Ian

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


#21131

FromChris Rebert <clp2@rebertia.com>
Date2012-03-02 00:08 -0800
Message-ID<mailman.345.1330675701.3037.python-list@python.org>
In reply to#21125
On Thu, Mar 1, 2012 at 11:16 PM, John Salerno <johnjsal@gmail.com> wrote:
>> That's just a coincidence. Your supercall is ought to be: super().move()
>> In contrast, super().move(self) calls the superclass instance method
>> `move` with 2 arguments, both `self`, which just happens to work given
>> your move() method, inside which `cls` isn't actually a class like it
>> ought to be.
>
> Thank you! This is the whole reason I tried using a class method in the first place. I was getting an error that said my move method only takes one argument, but I was passing in two.
>
> But if I make the super call as super().move(), how does that work? The move method in the superclass takes an argument, and if I just do super().move(), isn't it the subclass that's getting passed to it?

The instance of the subclass (i.e. what Pawn.move() considers `self`)
gets passed to it.

> How does the superclass move method know what 'self' is if it doesn't get passed to it as I did originally?

Oh, but it does get passed, just implicitly. `super()` basically grabs
`self` magically from its caller, and uses it to bind method calls on
the magical object returned by `super()`.

`super().move()` ends up being, in this particular case, equivalent to:
    ChessPiece.move(self)
which is incidentally how one would write this without using super().

Here is a useful[1] "identity" to ponder:
    x.y(z) === type(x).y(x, z)

Cheers,
Chris
--
[1]: In the sense of a useful lie[2]; it's far from completely
accurate; it (at the least) ignores metaclasses, overridings of
__getattribute__(), and a third thing that's difficult to clearly put
into words.
[2]: http://c2.com/cgi/wiki?UsefulLie [3]
[3]: Yes, my footnotes have footnotes.
http://rebertia.com

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


#21139

FromJohn Salerno <johnjsal@gmail.com>
Date2012-03-02 10:51 -0800
Message-ID<18263375.25.1330714301799.JavaMail.geo-discussion-forums@vbdj6>
In reply to#21131
> Oh, but it does get passed, just implicitly. `super()` basically grabs
> `self` magically from its caller, and uses it to bind method calls on
> the magical object returned by `super()`.

Thanks again, now I understand :)

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


#21140

FromJohn Salerno <johnjsal@gmail.com>
Date2012-03-02 10:51 -0800
Message-ID<mailman.347.1330714310.3037.python-list@python.org>
In reply to#21131
> Oh, but it does get passed, just implicitly. `super()` basically grabs
> `self` magically from its caller, and uses it to bind method calls on
> the magical object returned by `super()`.

Thanks again, now I understand :)

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


#21126

FromJohn Salerno <johnjsal@gmail.com>
Date2012-03-01 23:16 -0800
Message-ID<mailman.342.1330672617.3037.python-list@python.org>
In reply to#21122
> That's just a coincidence. Your supercall is ought to be: super().move()
> In contrast, super().move(self) calls the superclass instance method
> `move` with 2 arguments, both `self`, which just happens to work given
> your move() method, inside which `cls` isn't actually a class like it
> ought to be.

Thank you! This is the whole reason I tried using a class method in the first place. I was getting an error that said my move method only takes one argument, but I was passing in two.

But if I make the super call as super().move(), how does that work? The move method in the superclass takes an argument, and if I just do super().move(), isn't it the subclass that's getting passed to it? How does the superclass move method know what 'self' is if it doesn't get passed to it as I did originally?

[toc] | [prev] | [standalone]


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


csiph-web