[Tutor] What's in a name?
Keith Winston
keithwins at gmail.com
Fri Jan 3 21:03:20 CET 2014
On Fri, Jan 3, 2014 at 6:41 AM, Alan Gauld <alan.gauld at btinternet.com>wrote:
> This is off topic but a couple of points about the OOP stuff...
>
>
thanks Alan, this was helpful.
> "If I'm iterating a variable through a series of list names,
> for future processing, I would like to print the name of the
> list the variable is set to in a given moment... "
>
> Remember that variables in Python are just names.
> So we can rewrite your statement as
>
> "If I'm iterating a name through a series of list names, for future
> processing, I would like to print the name of the list the name is set to
> in a given moment... "
>
> And since the list names are just strings we can write:
>
> "If I'm iterating a name through a list of strings, for future processing,
> I would like to print the name in a given moment...
>
> So the answer to your question is just to print the string.
> The real challenge, as we have discovered, is how to access
> the list that is named by the string. And the usual way to
> map strings to objects is via a dictionary not by using eval().
>
>
Here's the thing: I think most of my "problems" go away with better design.
But in case I'm wrong, what I was trying to do, which I would think could
sometimes be helpful, is printing the name of an object along with it's
output/results... I don't think there's any way to do the opposite of
eval(), that is, create a string from an object name. Or am I just missing
something here (I THINK the right way to do this is add, if necessary, and
__name__ method, or at least a .name attribute, to the class... though now
that I think about it I think that still doesn't solve the problem, it
names the class not the instance.
Do you really need the num_xxx variables?
> Using len(xxx_list) is more reliable that depending on your
> code to maintain the values. It may be that you need them
> for a performance optimisation but given that games are
> not normally CPU bound that seems unlikely.
>
>
It was something between performance optimization and historical artifact.
I'm pretty sure the effect of it's optimization was to slow the program
down. It/they are redundant.
>
> return [tchutes, tladders] # only one will be != 0
>>
>
> I don't understand the tchutes/tladders stuff? They hold the
> target position or zero (the return comment is wrong BTW since both
> could be zero). Why not just have a single variable called target
> or somesuch? Also if you must return two values its probably better to use
> a tuple rather than a list.
>
>
Oh god, you are airing all my dirty laundry. On each move, the position
might be a chute, or a ladder, or neither. After I use that position to
determine if it's a chute or ladder, it seems like it makes sense to store
that info explicitly, to avoid another dictionary lookup. Probably another
optimization mistake. So if the first returned list entry has a number in
it, it's a chute, and add it to the list of chutes this game traversed, and
same with the second entry and ladder... I suspect I should do this
entirely differently.
>
> Shouldn't the self.position assignment be part of reset()?
>
>
It used to be, but then I realized it's not a state I need to save: I meant
to change it to a local variable.
>
> while self.position < 100:
>> gamecandl = self.move() # [chute, ladder] or [0, 0]
>> if gamecandl[0] != 0: # populate chutes list
>> self.chutes_list.append(gamecandl[0])
>> if gamecandl[1] != 0: # populate ladders list
>> self.ladders_list.append(gamecandl[1])
>>
>
> Why don't you do this update of the lists in the move() code.
> It's where it logically happens and saves passing back the
> list/tuple and then having to test it here. This just adds
> extra work.
>
>
Hmm. That seems like a good point. I think it all shifts when I properly
implement the Game() class. Next draft.
>
> return [step, self.move_count, self.num_chutes,
>> self.num_ladders, self.chutes_list, self.ladders_list]
>>
>
> In OOP you rarely have to return attributes. And since step
> is passed in as an argument the caller already knows. So I
> don't think you really need to return anything here.
Yes, reading this is what helped me see the direction of the next rewrite.
Thanks.
>
> OK, I see now, you are storing the current state values
> after each game. Personally I'd probably create another
> method called (get_stats() or similar and have play() return
> success/failure.
>
>
ooooo.... success or failure. You're edging me towards exception handling.
Then your line above would be:
>
> return [self.get_stats() for i in range(gamecount) if self.play()]
>
> It keeps the purpose of the methods explicit. play() plays the game,
> get_stats() returns the data.
>
> But there is another more OOP approach.
> Create a game instance for each iteration.
> Then collect the instances which then hold the data.
> No need for all the extra arrays, return values, etc.
> It's by using and passing whole *objects* around that
> it is *Object Oriented*. We are trying to move away
> from knowing about the internal data.
Ah, I didn't read this before I figured it out, but I had essentially
exactly this insight. Very satisfying. Thanks!
I think the rest of your comments more or less riff on this, and I
mentioned some similar ideas in a response I already made. It's very
helpful to have them reinforced though! Thanks for your thorough overview.
Keith
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/tutor/attachments/20140103/57406e9b/attachment.html>
More information about the Tutor
mailing list