Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

"Battleship" style game

10 views
Skip to first unread message

Shawn Milochik

unread,
Feb 25, 2009, 11:29:25 AM2/25/09
to Python List
I started learning Java for fun, and the first project assignment in
the book is to create a game like "Battleship." So, of course, I wrote
it in Python first, just for fun. I haven't had the time to look up
all the Java syntax.

So, here it is, fully functional. I thought I'd throw it out there and
see if anyone would like to offer any useful tips. I'm not claiming
it's bulletproof, but it works. I just kind of came up with all the
methods off of the top of my head, so if anyone has any suggestions
for more elegant or efficient code, please let me know.

http://shawnmilo.com/ships/

Thanks,
Shawn

Marco Mariani

unread,
Feb 25, 2009, 11:38:05 AM2/25/09
to
Shawn Milochik wrote:

> I'm not claiming it's bulletproof, but it works. I just kind of came
up with all the
> methods off of the top of my head, so if anyone has any suggestions
> for more elegant or efficient code, please let me know.

Yes it's in Python alright, but it's not Pythonese yet. You could try
avoiding the getter/setter stuff, and camelCase method naming, things
like that, for a start.

Shawn Milochik

unread,
Feb 25, 2009, 11:50:18 AM2/25/09
to Python List
On Wed, Feb 25, 2009 at 11:38 AM, Marco Mariani <ma...@sferacarta.com> wrote:
>
> Yes it's in Python alright, but it's not Pythonese yet. You could try
> avoiding the getter/setter stuff, and camelCase method naming, things like
> that, for a start.
>
> --
> http://mail.python.org/mailman/listinfo/python-list
>


What do you mean avoiding the getter/setter stuff? If I understand
correctly, you're saying to directly access the attributes, which I
specifically want to avoid because I may want to enforce some rules
(such as not changing a ship length after it's created).

The camel-case thing I get -- I use that and this_type quite a bit,
probably because of the inconsistency of the languages I use
regularly, and standards at work and conventions in my hobby
programming.

Steve Holden

unread,
Feb 25, 2009, 12:01:21 PM2/25/09
to pytho...@python.org
Shawn Milochik wrote:
> On Wed, Feb 25, 2009 at 11:38 AM, Marco Mariani <ma...@sferacarta.com> wrote:
>> Yes it's in Python alright, but it's not Pythonese yet. You could try
>> avoiding the getter/setter stuff, and camelCase method naming, things like
>> that, for a start.
>>
>> --
>> http://mail.python.org/mailman/listinfo/python-list
>>
>
>
> What do you mean avoiding the getter/setter stuff? If I understand
> correctly, you're saying to directly access the attributes, which I
> specifically want to avoid because I may want to enforce some rules
> (such as not changing a ship length after it's created).
>
If you wanted to enforce those restrictions you could just turn
attributes into properties.

> The camel-case thing I get -- I use that and this_type quite a bit,
> probably because of the inconsistency of the languages I use
> regularly, and standards at work and conventions in my hobby
> programming.

PEP 008 is the usual style recommendation.

regards
Steve
--
Steve Holden +1 571 484 6266 +1 800 494 3119
Holden Web LLC http://www.holdenweb.com/

Gabriel Genellina

unread,
Feb 25, 2009, 12:07:07 PM2/25/09
to pytho...@python.org
En Wed, 25 Feb 2009 14:50:18 -0200, Shawn Milochik <Sh...@milochik.com>
escribió:

> On Wed, Feb 25, 2009 at 11:38 AM, Marco Mariani <ma...@sferacarta.com>
> wrote:
>>
>> Yes it's in Python alright, but it's not Pythonese yet. You could try
>> avoiding the getter/setter stuff, and camelCase method naming, things
>> like
>> that, for a start.
>
> What do you mean avoiding the getter/setter stuff? If I understand
> correctly, you're saying to directly access the attributes, which I
> specifically want to avoid because I may want to enforce some rules
> (such as not changing a ship length after it's created).

I think Marco Mariani was suggesting something like this:

class Ship(object):

def __init__(self, length):
self._length = length

def get_length(self):
return self._length
length = property(get_length) # a read only property

--
Gabriel Genellina

Shawn Milochik

unread,
Feb 25, 2009, 1:33:48 PM2/25/09
to Python List
Thanks. I wasn't aware of the property() function, but I read up on
it. I modified the Vessels.py file, but not the board file (except
where necessary to handle the changes made to Vessels. Is this better?

http://shawnmilo.com/ships/ships2/

Diez B. Roggisch

unread,
Feb 25, 2009, 3:15:40 PM2/25/09
to
Shawn Milochik schrieb:


Not really. The point about properties is that you *can* make attribute
access trigger getter or setter code.

But not that you do unless there is an actual reason for that. The way
you do it now is simply introducing clutter, without benefit. Your class
would be half the current size - without loss of functionality.

Diez

Shawn Milochik

unread,
Feb 25, 2009, 3:54:46 PM2/25/09
to Python List
On Wed, Feb 25, 2009 at 3:15 PM, Diez B. Roggisch <de...@nospam.web.de> wrote:

> Not really. The point about properties is that you *can* make attribute
> access trigger getter or setter code.
>
> But not that you do unless there is an actual reason for that. The way you
> do it now is simply introducing clutter, without benefit. Your class would
> be half the current size - without loss of functionality.
>
>
>
> Diez

> --
> http://mail.python.org/mailman/listinfo/python-list
>

It is true that it would be fewer lines of code with the same
functionality, but it's better practice to have that framework in
place so that any changes made in the future wouldn't break any of the
code accessing my class. Obviously this is a fairly simple game that
has a fixed set of rules, but I'm trying to cultivate good habits, and
I don't think that doing it this way is anti-Pythonic.

Unless, of course, anything I said is wrong, which is always possible.
If I'm missing a bigger-picture idea, I'd like to know about it.

Thanks,
Shawn

Steve Holden

unread,
Feb 25, 2009, 4:07:36 PM2/25/09
to pytho...@python.org
Shawn Milochik wrote:
> On Wed, Feb 25, 2009 at 3:15 PM, Diez B. Roggisch <de...@nospam.web.de> wrote:
>
>> Not really. The point about properties is that you *can* make attribute
>> access trigger getter or setter code.
>>
>> But not that you do unless there is an actual reason for that. The way you
>> do it now is simply introducing clutter, without benefit. Your class would
>> be half the current size - without loss of functionality.
>>
>>
>>
>> Diez
>> --
>> http://mail.python.org/mailman/listinfo/python-list
>>
>
> It is true that it would be fewer lines of code with the same
> functionality, but it's better practice to have that framework in
> place so that any changes made in the future wouldn't break any of the
> code accessing my class. Obviously this is a fairly simple game that
> has a fixed set of rules, but I'm trying to cultivate good habits, and
> I don't think that doing it this way is anti-Pythonic.
>
> Unless, of course, anything I said is wrong, which is always possible.
> If I'm missing a bigger-picture idea, I'd like to know about it.
>
The point of using property() is that you can start out using attribute
access on its own (which is the standard Python way to do things:
getters and setters are seen by most as redundant code).

Once you need programmed access on read and/or write, leave the client
code (the code that accesses the attributes) as it is, but turn the
attributes into properties so that the functions are invoked
automatically on attribute-style access.

So I believe what Diez was saying is that by using properties in your
existing code you are getting the worst of both worlds - unnecessarily
complex objects, and code that uses those objects by calling methods
when it could be accessing attributes (or properties - depending on the
implementation). At least this is true of your Ship test code.

J. Cliff Dyer

unread,
Feb 25, 2009, 4:14:58 PM2/25/09
to Shawn Milochik, Python List
On Wed, 2009-02-25 at 15:54 -0500, Shawn Milochik wrote:
> On Wed, Feb 25, 2009 at 3:15 PM, Diez B. Roggisch <de...@nospam.web.de> wrote:
>
> > Not really. The point about properties is that you *can* make attribute
> > access trigger getter or setter code.
> >
> > But not that you do unless there is an actual reason for that. The way you
> > do it now is simply introducing clutter, without benefit. Your class would
> > be half the current size - without loss of functionality.
> >
> >
> >
> > Diez
> > --
> > http://mail.python.org/mailman/listinfo/python-list
> >
>
> It is true that it would be fewer lines of code with the same
> functionality, but it's better practice to have that framework in
> place so that any changes made in the future wouldn't break any of the
> code accessing my class. Obviously this is a fairly simple game that
> has a fixed set of rules, but I'm trying to cultivate good habits, and
> I don't think that doing it this way is anti-Pythonic.
>
> Unless, of course, anything I said is wrong, which is always possible.
> If I'm missing a bigger-picture idea, I'd like to know about it.
>

The piece you're missing is exactly why properties are so cool.

They take what looks like attribute access from the client side, and
pass it through a method. So while you can add any sort of changes you
want to make can be made without breaking any client code. To them, it
still looks like attribute access.

class Foo(object):
a = 4

class Bar(object):
def __init__(self):
self._a = 4

def _get_a(self):
return self._a

def _set_a(self, value):
if not value % 2:
self._a = value
a = property(_get_a, _set_a)

>>> foo = Foo()
>>> foo.a
4
>>> foo.a = 5
>>> foo.a
5
>>> bar = Bar()
>>> bar.a
4
>>> bar.a = 5
>>> bar.a
4
>>> bar.a = 6
>>> bar.a
6

> Thanks,
> Shawn
> --
> http://mail.python.org/mailman/listinfo/python-list
>

Diez B. Roggisch

unread,
Feb 25, 2009, 4:32:53 PM2/25/09
to
Shawn Milochik schrieb:

You miss that Java has no properties, and thus forces prorgammers to
wrap all attribute-access into getter/setters - just in case one wants
something other than pure attribute access in some distant future to come.

In Python this is not needed. If something starts as an attribute, and
then evolves so that it needs more complex logic when being accessed,
you introduce a property of the same name.


Don't waste time coding for a future you can't even pretend to know. Do
what is needed to solve the actual problem.


Diez

Grant Edwards

unread,
Feb 25, 2009, 4:39:09 PM2/25/09
to
On 2009-02-25, Diez B. Roggisch <de...@nospam.web.de> wrote:

> Don't waste time coding for a future you can't even pretend to
> know. Do what is needed to solve the actual problem.

Premature obfuscation is even worse than premature optimization.

--
Grant Edwards grante Yow! Well, O.K.
at I'll compromise with my
visi.com principles because of
EXISTENTIAL DESPAIR!

Jean-Paul Calderone

unread,
Feb 25, 2009, 5:31:55 PM2/25/09
to pytho...@python.org
On Wed, 25 Feb 2009 15:54:46 -0500, Shawn Milochik <sh...@milochik.com> wrote:
>On Wed, Feb 25, 2009 at 3:15 PM, Diez B. Roggisch <de...@nospam.web.de> wrote:
>
>> Not really. The point about properties is that you *can* make attribute
>> access trigger getter or setter code.
>>
>> But not that you do unless there is an actual reason for that. The way you
>> do it now is simply introducing clutter, without benefit. Your class would
>> be half the current size - without loss of functionality.
>>
>>
>>
>> Diez
>> --
>> http://mail.python.org/mailman/listinfo/python-list
>>
>
>It is true that it would be fewer lines of code with the same
>functionality, but it's better practice to have that framework in
>place so that any changes made in the future wouldn't break any of the
>code accessing my class. Obviously this is a fairly simple game that
>has a fixed set of rules, but I'm trying to cultivate good habits, and
>I don't think that doing it this way is anti-Pythonic.
>
>Unless, of course, anything I said is wrong, which is always possible.
>If I'm missing a bigger-picture idea, I'd like to know about it.

Much better practice would be writing unit tests for the behavior you
want. This is a vastly greater measure of protection against future
maintenance introducing bugs than the restrictions you're adding to
your implementation. So if you're looking for good habits to pick up,
start with unit testing. Your test.py files show you're at least
thinking about testing, but you should take a look at something like
the `unittest´ module in the standard library and take things to the
next level.

Jean-Paul

Zvezdan Petkovic

unread,
Feb 25, 2009, 9:11:13 PM2/25/09
to Python List
On Feb 25, 2009, at 3:54 PM, Shawn Milochik wrote:
> It is true that it would be fewer lines of code with the same
> functionality, but it's better practice to have that framework in
> place so that any changes made in the future wouldn't break any of the
> code accessing my class. Obviously this is a fairly simple game that
> has a fixed set of rules, but I'm trying to cultivate good habits, and
> I don't think that doing it this way is anti-Pythonic.

Well, they are trying to help you with the best practices.
You offered the code for review and they reviewed it.
Whether you'll accept what they say or deny it is your call, of course.

FWIW, the Pythonic way would be:

>>> class Ship(object):
... def __init__(self, length):
... self._length = length
... @property
... def length(self):
... return self._length
...
>>> s = Ship(5)
>>> s.length
5
>>> # notice how the property is read-only which is what you wanted
>>> s.length = 7
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: can't set attribute
>>> ^D

Using @property decorator makes a read-only property. If you need a
read/write property there are several ways to define setter and
deleter methods with or without decorators.

I hope you see that

x = s.length
s.position = y

is a completely different style than

x = s.get_length()
s.set_position(y)

Most of the people who program in Python prefer the first style above.

Lie

unread,
Feb 26, 2009, 5:39:12 PM2/26/09
to
On Feb 26, 3:50 am, Shawn Milochik <Sh...@Milochik.com> wrote:
> On Wed, Feb 25, 2009 at 11:38 AM, Marco Mariani <ma...@sferacarta.com> wrote:
>
> > Yes it's in Python alright, but it's not Pythonese yet. You could try
> > avoiding the getter/setter stuff, and camelCase method naming, things like
> > that, for a start.
>
> > --
> >http://mail.python.org/mailman/listinfo/python-list
>
> What do you mean avoiding the getter/setter stuff? If I understand
> correctly, you're saying to directly access the attributes, which I
> specifically want to avoid because I may want to enforce some rules
> (such as not changing a ship length after it's created).

I just want to add the note that since you're planning to move the
code to Java, although you should avoid getter and setter in python
(since it's redundant because of property), you should use getter and
setter in the Java version because it is the best practice in Java.

Shawn Milochik

unread,
Mar 11, 2009, 2:13:01 PM3/11/09
to Python List
Thanks for the tips, everybody.

I've cleaned it up, and learned some useful things from your comments
and the reading they led to.

http://shawnmilo.com/ships/

Falstaff

unread,
Mar 26, 2009, 3:24:09 PM3/26/09
to

I certainly didn't expect this thread to end like this. Sure, most
Python people prefer properties over straight accessors, but that is
just reworking the methods in the class, and not the reworking the
object model itself. Thus stopping at 'use properties' misses out on
the one, true promised land of data encapsulation. See e.g.

"Why getter and setter methods are evil"
...Don't ask for the information you need to do the work;
ask the object that has the information to do the work for you...
Allen Holub
http://www.javaworld.com/javaworld/jw-09-2003/jw-0905-toolbox.html?page=3

or any other number of OO references on data encapsulation. This can
even apply to GUI objects now - rather than having the GUI object pull
data from the model object, you have the model draw itself w/ a
draw_myself method, perhaps implemented by a handler.

That goes for Java too, AFAIK.

0 new messages