Is this the proper way to use a class method?

J

John Salerno

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 pieceas 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)
 
C

Chris Rebert

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 classmethod is that it can be called by the class itself, even before instanceshave been created. Yet the way I've implemented it, it is necessarily tiedto being called on an instance. Is this wrong? Is there a better way to dowhat 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.

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
 
J

John Salerno

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 didoriginally?
 
J

John Salerno

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 didoriginally?
 
I

Ian Kelly

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
 
C

Chris Rebert

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
 
J

John Salerno

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 :)
 
J

John Salerno

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 :)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,578
Members
45,052
Latest member
LucyCarper

Latest Threads

Top