[Tutor] First code snipet

Dave Angel davea at ieee.org
Sun Jul 26 13:49:36 CEST 2009


Darth Kaboda wrote:
>  
>
>   
>> Subject: Re: [Tutor] First code snipet
>> From: andreas at kostyrka.org
>> To: darthkaboda at msn.com
>> CC: tutor at python.org
>> Date: Sun, 26 Jul 2009 03:02:27 +0200
>>
>> Some things:
>>
>> 1) It's Python, not Phython.
>> 2) Slightly shorter solution to your problem:
>>
>> import random
>>
>> input = range(53)
>> random.shuffle(input)
>> print input
>>
>> 3) The important part here is that reimplementing something that is in
>> the standard library does not make sense usually.
>>
>> 4) A more sensible implementation of shuffle comes directly out of
>> random.py:
>>
>> def shuffle(self, x, random=None, int=int):
>> """x, random=random.random -> shuffle list x in place; return
>> None.
>>
>> Optional arg random is a 0-argument function returning a random
>> float in [0.0, 1.0); by default, the standard random.random.
>> """
>>
>> if random is None:
>> random = self.random
>> for i in reversed(xrange(1, len(x))):
>> # pick an element in x[:i+1] with which to exchange x[i]
>> j = int(random() * (i+1))
>> x[i], x[j] = x[j], x[i]
>>
>> Notice that it is not exactly optimal, one could easily replace the
>> reversed(xrange()) expression with a 3 parameter version of xrange:
>> for i in xrange(len(x) - 1, 0, -1):
>>
>> Andreas
>>
>>
>>
>> Am Samstag, den 25.07.2009, 17:15 -0700 schrieb Darth Kaboda:
>>     
>>> I'm starting to learn Python as it seems to be adopted by many
>>> companies that I've been looking to apply to. I used the book Learning
>>> Phython to get the basics of the language and many of the gotcha's. I
>>> think I know enough of the basic features of the language to start
>>> playing around and can understand most code I've seen so far by
>>> looking at some of the posts here.
>>>
>>> The one worry I have is not coding things the Phython way as I've been
>>> a Visual Basic programmer for so long and a C++ programmer before
>>> that. So would like to have people look at a simplistic class
>>> (shuffles lists of objects wrote it for shuffling cards but
>>> with Phython could be used for any "list" type object) I wrote to give
>>> me some feedback on the style of it.
>>>
>>> Any feedback is appreciated.
>>>
>>> Thanks,
>>> Brian
>>> _______________________________________________
>>> Tutor maillist - Tutor at python.org
>>> http://mail.python.org/mailman/listinfo/tutor
>>>       
>
>  
>
> Thanks for the correction not sure why I typed it that way after typing it correctly in the first sentence, must have wondered off somewhere in my mind I guess. 
>
>  
>
> Oops I guess I should have also mentioned what I was trying to accomplish with this class. I wanted to mimic how a deck of cards get's shuffled in the real world. i.e. split the deck and shuffle the two halves together. 
>
>  
>
> Brian
>
>
>  
>
>   
Good point.  It is important to state your goal for the code, preferably 
in comments in your code, as well as in the message asking us the 
question.  Suggest you include a doc-string for each class and method 
declaration.

But it's important to tell us how you expect to use it, as well.  If 
it's for your own learning, then it's pretty good as it is.  But if you 
intend to show it to prospective employers, there are a lot of ways to 
clean it up.


So...

Unlike Java, not everything needs to be in a class.  This shuffler class 
accomplishes nothing that the module doesn't already do.  The only 
instance attribute you use is rgen, and that could just as readily have 
been a global (visible within the entire module).

Naming is important.  I think I would have factored it into three 
functions  cut() and ripple().  shuffle() simply calls cut(), then ripple().

You need to know the library better.  Andreas already mentioned the std 
library random.shuffle(), and you correctly explained why you didn't use 
it.  But there are other library functions that would make your code 
more concise, more readable, and maybe faster.

Starting with shuffle() (which I'd call ripple())

Because Python makes it easy to swap two variables in-place, it's common 
to swap arguments directly, rather than copy them to local attributes.  
So I'd replace the first 4 lines with:
   if self.rgen.randint(0,1):  #randomly decide which pile is shuffled 
down first
            inpile2, inpile1 = inpile1, inpile2

len() is very fast, so there's no need for a separate variable to keep 
track of the lengths of inpile1 and inpile2.  So eliminate all refs to 
pile1c and pile2.  In the while, just use
    while  len(inpile1) and len(inpile2):

Lists have no type associated with them.  Each object in a list has its 
own type.  So there's no meaning to constructing an empty list out of 
another one.
     rpile = []

pop(0) is slow, compared with pop(-1).  If you used the latter, you 
would have to do a reverse on the list when you were done to keep the 
realism.  And that would make the code less readable.  So I think this 
is an unnecessary optimization.  But keep it in mind if you're ever 
dealing with thousands of items in a list. Peeling them off from the 
front one at a time will be slow.

The logic of popping a random number of cards from one list, and 
appending them to the result could be done the same way you do the 
cut(), using slices.  I think it would be worth it if you made a 
separate function out of it, to call from whichever deck was being 
operated on.

Where you do the    if i < pile1c     you could instead use the min() 
function.
    i = min(len(inpile1), self.rgen.randint(1,4))

At the end of the function, the  if pile1c:  elif ...  logic could be 
replaced by
     rpile.extend(inpile1).extend(inpile2)

as there's no harm in extending with an empty list.

HTH,   DaveA



More information about the Tutor mailing list