Re: [Tutor] Giving a name to a function and calling it, rather than calling the function directly

2010-09-05 Thread lists
>  On 9/4/2010 10:14 AM, lists wrote:
>>
>> Hi folks,
>>
>> I'm new to Python, I'm working my way through some intro books, and I
>> have a question that I wonder if someone could help me with please?
>>
>> This is my attempt at solving an exercise where the program is
>> supposed to flip a coin 100 times and then tell you the number of
>> heads and tails.
>>
>> ATTEMPT 1 returns:
>>
>> The coin landed on tails 100 times
>>
>> The coin landed on heads 0 times
>>
>> ATTEMPT 2 returns:
>>
>> The coin landed on tails 75 times
>>
>> The coin landed on heads 25 times
>>
>> I expected to see the result in attempt 2. I don't fully understand
>> why the results are different however. Is it because Python only runs
>> the randint function once when I call it by the name I assigned to it
>> in attempt 1, but it runs the function fully on each iteration of the
>> loop in attempt 2? Why are these two things different?
>>
>> Thanks in advance,
>>
>> Chris
>> --
>> ATTEMPT 1
>> --
>> import random
>>
>> heads = 0
>> tails = 0
>> tossNo = 0
>> toss = random.randint(1,2)
>>
>> while tossNo<= 99:
>>     if toss == 1:
>>         heads += 1
>>         tossNo += 1
>>     elif toss == 2:
>>          tails += 1
>>          tossNo += 1
>>
>> print "The coin landed on tails " + str(tails) + " times \n"
>> print "The coin landed on heads " + str(heads) + " times \n"
>>
>> --
>> ATTEMPT 2
>> --
>> import random
>>
>> heads = 0
>> tails = 0
>> tossNo = 0
>>
> You should have only 1 call to randint in the loop
>>
>> while tossNo<= 99:
>>     if random.randint(1,2) == 1:
>>         heads += 1
>>         tossNo += 1
>>     else:
>>          tails += 1
>>          tossNo += 1
>>
>> print "The coin landed on tails " + str(tails) + " times \n"
>> print "The coin landed on heads " + str(heads) + " times \n"
>
> You can also simplify:
>
> import random
> heads = 0
> tosses = 100
> for i in range(tosses):
>    heads += random.randint(0,1)
> print "The coin landed on tails " + str(tosses - heads) + " times \n"
> print "The coin landed on heads " + str(heads) + " times \n"
>
> Or even simpler:
>
> import random
> tosses = 100
> heads = sum(random.randint(0,1) for i in range(tosses))
> print ...
>
>
> --
> Bob Gailer
> 919-636-4239
> Chapel Hill NC
>

Thanks again all! Hopefully as I learn more I'll find it easier to
make the most efficient design choices :-)

Chris
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Giving a name to a function and calling it, rather than calling the function directly

2010-09-04 Thread bob gailer

 On 9/4/2010 10:14 AM, lists wrote:

Hi folks,

I'm new to Python, I'm working my way through some intro books, and I
have a question that I wonder if someone could help me with please?

This is my attempt at solving an exercise where the program is
supposed to flip a coin 100 times and then tell you the number of
heads and tails.

ATTEMPT 1 returns:

The coin landed on tails 100 times

The coin landed on heads 0 times

ATTEMPT 2 returns:

The coin landed on tails 75 times

The coin landed on heads 25 times

I expected to see the result in attempt 2. I don't fully understand
why the results are different however. Is it because Python only runs
the randint function once when I call it by the name I assigned to it
in attempt 1, but it runs the function fully on each iteration of the
loop in attempt 2? Why are these two things different?

Thanks in advance,

Chris
--
ATTEMPT 1
--
import random

heads = 0
tails = 0
tossNo = 0
toss = random.randint(1,2)

while tossNo<= 99:
 if toss == 1:
 heads += 1
 tossNo += 1
 elif toss == 2:
  tails += 1
  tossNo += 1

print "The coin landed on tails " + str(tails) + " times \n"
print "The coin landed on heads " + str(heads) + " times \n"

--
ATTEMPT 2
--
import random

heads = 0
tails = 0
tossNo = 0


You should have only 1 call to randint in the loop

while tossNo<= 99:
 if random.randint(1,2) == 1:
 heads += 1
 tossNo += 1
 else:
  tails += 1
  tossNo += 1

print "The coin landed on tails " + str(tails) + " times \n"
print "The coin landed on heads " + str(heads) + " times \n"


You can also simplify:

import random
heads = 0
tosses = 100
for i in range(tosses):
heads += random.randint(0,1)
print "The coin landed on tails " + str(tosses - heads) + " times \n"
print "The coin landed on heads " + str(heads) + " times \n"

Or even simpler:

import random
tosses = 100
heads = sum(random.randint(0,1) for i in range(tosses))
print ...


--
Bob Gailer
919-636-4239
Chapel Hill NC

___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Giving a name to a function and calling it, rather than calling the function directly

2010-09-04 Thread Steven D'Aprano
On Sun, 5 Sep 2010 08:39:07 am lists wrote:

> while tossNo <= 99:
> coinToss = random.randint

Move that out of the loop. There's no need to make the assignment 100 
times.

> tossNo += 1
> if coinToss(1,2) == 1:
> heads += 1
> else:
> tails += 1


Rather than count the number of loops yourself, let Python do the 
counting:

import random
coinToss = random.randint
heads = tails = 0
for tossNo in range(100):
if coinToss(1, 2) == 1:
heads += 1
else: 
tails += 1



Can we do better? Absolutely! Since we know that there are exactly 100 
coin tosses, and the number of heads plus the number of tails makes 
100, why are we counting them both?


import random
coinToss = random.randint
heads = 0
for tossNo in range(100):
if coinToss(1, 2) == 1:
heads += 1

print "The coin landed on tails " + str(100-heads) + " times."
print "The coin landed on heads " + str(heads) + " times."

One small weakness -- if we ever decide to change the number of coin 
tosses from 100 to some other number, we have to remember to change 100 
in two places. We can fix that by defining a named constant. Python 
doesn't actually have constants, so we use the naming convention "all 
uppercase means this is a constant, please don't modify it":


import random
coinToss = random.randint
heads = 0
COUNT = 100
for tossNo in range(COUNT):
if coinToss(1, 2) == 1:
heads += 1

print "The coin landed on tails " + str(COUNT-heads) + " times."
print "The coin landed on heads " + str(heads) + " times."


Can we do better? Absolutely -- nothing says that heads must be 1 and 
tails 2. If we make heads 1 and tails 0, we get a neat optimization:

import random
coinToss = random.randint
heads = 0
COUNT = 100
for tossNo in range(COUNT):
heads += coinToss(0, 1)



Can we do better? Yes. The function "coinToss" is misleading. It doesn't 
toss a coin, not even figuratively speaking -- it takes two arguments, 
and returns an integer between those two limits. How is that related to 
tossing a coin? What are you going to do, this?

coinToss(1, 7)  # toss a seven-sided coin

No, that's ridiculous, and so the name is misleading. What your function 
does is return a random integer. That's no surprise, because it's just 
random.randint renamed. So let's fix that by making a proper coinToss 
function:

import random
def coinToss():
return random.randint(0, 1)

heads = 0
COUNT = 100
for tossNo in range(COUNT):
heads += coinToss()


Can we do better? Yes, for some definition of "better":

import random
import functools
coinToss = functools.partial(random.randint, 0, 1)
COUNT = 100
heads = sum(coinToss() for tossNo in range(COUNT))
print "The coin landed on tails %d times." % (COUNT-heads)
print "The coin landed on heads %d times." % heads


It's certainly short and concise. You should be able to guess what sum 
does, and if you can guess what functools.partial does you're doing 
well :)



-- 
Steven D'Aprano
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Giving a name to a function and calling it, rather than calling the function directly

2010-09-04 Thread lists
>>     if coinToss(1,2) == 1:
>>         heads += 1
>>         tossNo += 1
>>     else:
>>         tails += 1
>>         tossNo += 1
>
> Looking good. You can hoist "tossNo += 1" out of each branch of your if
> statement too, if you like, to make it even more streamlined (In
> other words, execute it once, right after the coin flip, and before
> the if-statement).
>
> Alan

Ah right, I get you. i.e

while tossNo <= 99:
coinToss = random.randint
tossNo += 1
if coinToss(1,2) == 1:
heads += 1
else:
tails += 1

That makes sense. :-)

Chris
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Giving a name to a function and calling it, rather than calling the function directly

2010-09-04 Thread R. Alan Monroe
> if coinToss(1,2) == 1:
> heads += 1
> tossNo += 1
> else:
> tails += 1
> tossNo += 1

Looking good. You can hoist "tossNo += 1" out of each branch of your if
statement too, if you like, to make it even more streamlined (In
other words, execute it once, right after the coin flip, and before
the if-statement).

Alan

___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Giving a name to a function and calling it, rather than calling the function directly

2010-09-04 Thread lists
>> On 9/4/10, lists  wrote:
>> > Hi folks,
>> >
>> > I'm new to Python, I'm working my way through some intro books, and I
>> > have a question that I wonder if someone could help me with please?
>> >
>> > This is my attempt at solving an exercise where the program is
>> > supposed to flip a coin 100 times and then tell you the number of
>> > heads and tails.
>> >
>> > ATTEMPT 1 returns:
>> >
>> > The coin landed on tails 100 times
>> >
>> > The coin landed on heads 0 times
>> >
>> > ATTEMPT 2 returns:
>> >
>> > The coin landed on tails 75 times
>> >
>> > The coin landed on heads 25 times
>> >
>> > I expected to see the result in attempt 2. I don't fully understand
>> > why the results are different however. Is it because Python only runs
>> > the randint function once when I call it by the name I assigned to it
>> > in attempt 1, but it runs the function fully on each iteration of the
>> > loop in attempt 2? Why are these two things different?
>> Exactly. Essentially when you say
>> x=random.randint(1,2)
>> you are putting the value returned by randint into x, and this happens
>> only once. Had you moved that assignment into the while loop it would
>> keep replacing x, or toss in your case, with a random integer, but
>> because you just call it once it is only assigned once. Python, or any
>> language, would have no way of knowing that you want to reassign toss
>> each time. Loops are used to repeat actions, but you left the
>> assignment of your random int outside of the loop in attempt1 and so
>> there is no way for Python to know that you actually want toss updated
>> 100 times. I hope I explained this okay.
>> >
>> > Thanks in advance,
>> >
>> > Chris
>> > --
>> > ATTEMPT 1
>> > --
>> > import random
>> >
>> > heads = 0
>> > tails = 0
>> > tossNo = 0
>> > toss = random.randint(1,2)
>> >
>> > while tossNo <= 99:
>> > if toss == 1:
>> > heads += 1
>> > tossNo += 1
>> > elif toss == 2:
>> > tails += 1
>> > tossNo += 1
>> >
>> > print "The coin landed on tails " + str(tails) + " times \n"
>> > print "The coin landed on heads " + str(heads) + " times \n"
>> >
>> > --
>> > ATTEMPT 2
>> > --
>> > import random
>> >
>> > heads = 0
>> > tails = 0
>> > tossNo = 0
>> >
>> > while tossNo <= 99:
>> > if random.randint(1,2) == 1:
>> > heads += 1
>> > tossNo += 1
>> > elif random.randint(1,2) == 2:
>> > tails += 1
>> > tossNo += 1
>> >
>> > print "The coin landed on tails " + str(tails) + " times \n"
>> > print "The coin landed on heads " + str(heads) + " times \n"
>
> Alex has already answered the question you've asked. I would just like to
> point out a subtle bug in your ATTEMPT 2 code. What your code does is this:
>
> - generate a random number 1 or 2
> - test if it is 1
> - if it isn't, generate a *new* random number
> - test if this new random number is 2
>
> That the number of 1s and 2s add up to 100 is an accident of the way you are
> counting them.
>
> You should modify the code to generate a single random number each time
> through the loop and test whether it is 1 or 2.
>
> --
> sent from my Nokia N900
>

Thanks so much for your fast and friendly response guys, I'm bowled
over! As you can tell, I'm just starting out and it helps so much to
be able to get a helping hand like this.

I've taken on board what you have said and edited the code.

Kushal, it didn't occur to me that what I was doing in essence was
flipping a coin and attempting to get one result, then only flipping a
coin if I didn't get that first result. Now that I've edited the code
it gives much 'saner' results. I guess I'll have to be much more
careful in the future in the design stage!!

Here's what I have now:


import random

heads = 0
tails = 0
tossNo = 0

while tossNo <= 99:
coinToss = random.randint
if coinToss(1,2) == 1:
heads += 1
tossNo += 1
else:
tails += 1
tossNo += 1

print "The coin landed on tails " + str(tails) + " times \n"
print "The coin landed on heads " + str(heads) + " times \n"
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Giving a name to a function and calling it, rather than calling the function directly

2010-09-04 Thread Kushal Kumaran
- Original message -
> On 9/4/10, lists  wrote:
> > Hi folks,
> > 
> > I'm new to Python, I'm working my way through some intro books, and I
> > have a question that I wonder if someone could help me with please?
> > 
> > This is my attempt at solving an exercise where the program is
> > supposed to flip a coin 100 times and then tell you the number of
> > heads and tails.
> > 
> > ATTEMPT 1 returns:
> > 
> > The coin landed on tails 100 times
> > 
> > The coin landed on heads 0 times
> > 
> > ATTEMPT 2 returns:
> > 
> > The coin landed on tails 75 times
> > 
> > The coin landed on heads 25 times
> > 
> > I expected to see the result in attempt 2. I don't fully understand
> > why the results are different however. Is it because Python only runs
> > the randint function once when I call it by the name I assigned to it
> > in attempt 1, but it runs the function fully on each iteration of the
> > loop in attempt 2? Why are these two things different?
> Exactly. Essentially when you say
> x=random.randint(1,2)
> you are putting the value returned by randint into x, and this happens
> only once. Had you moved that assignment into the while loop it would
> keep replacing x, or toss in your case, with a random integer, but
> because you just call it once it is only assigned once. Python, or any
> language, would have no way of knowing that you want to reassign toss
> each time. Loops are used to repeat actions, but you left the
> assignment of your random int outside of the loop in attempt1 and so
> there is no way for Python to know that you actually want toss updated
> 100 times. I hope I explained this okay.
> > 
> > Thanks in advance,
> > 
> > Chris
> > --
> > ATTEMPT 1
> > --
> > import random
> > 
> > heads = 0
> > tails = 0
> > tossNo = 0
> > toss = random.randint(1,2)
> > 
> > while tossNo <= 99:
> > if toss == 1:
> > heads += 1
> > tossNo += 1
> > elif toss == 2:
> > tails += 1
> > tossNo += 1
> > 
> > print "The coin landed on tails " + str(tails) + " times \n"
> > print "The coin landed on heads " + str(heads) + " times \n"
> > 
> > --
> > ATTEMPT 2
> > --
> > import random
> > 
> > heads = 0
> > tails = 0
> > tossNo = 0
> > 
> > while tossNo <= 99:
> > if random.randint(1,2) == 1:
> > heads += 1
> > tossNo += 1
> > elif random.randint(1,2) == 2:
> > tails += 1
> > tossNo += 1
> > 
> > print "The coin landed on tails " + str(tails) + " times \n"
> > print "The coin landed on heads " + str(heads) + " times \n"

Alex has already answered the question you've asked.  I would just like to 
point out a subtle bug in your ATTEMPT 2 code.  What your code does is this:

- generate a random number 1 or 2
- test if it is 1
- if it isn't, generate a *new* random number
- test if this new random number is 2

That the number of 1s and 2s add up to 100 is an accident of the way you are 
counting them.

You should modify the code to generate a single random number each time through 
the loop and test whether it is 1 or 2.

-- 
sent from my Nokia N900
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Giving a name to a function and calling it, rather than calling the function directly

2010-09-04 Thread Dave Angel

lists wrote:

Hi folks,

I'm new to Python, I'm working my way through some intro books, and I
have a question that I wonder if someone could help me with please?

This is my attempt at solving an exercise where the program is
supposed to flip a coin 100 times and then tell you the number of
heads and tails.

ATTEMPT 1 returns:

The coin landed on tails 100 times

The coin landed on heads 0 times

ATTEMPT 2 returns:

The coin landed on tails 75 times

The coin landed on heads 25 times

I expected to see the result in attempt 2. I don't fully understand
why the results are different however. Is it because Python only runs
the randint function once when I call it by the name I assigned to it
in attempt 1, but it runs the function fully on each iteration of the
loop in attempt 2? Why are these two things different?

Thanks in advance,

Chris
--
ATTEMPT 1
--
import random

heads = 0
tails = 0
tossNo = 0
toss = random.randint(1,2)

while tossNo <= 99:
if toss == 1:
heads += 1
tossNo += 1
elif toss == 2:
 tails += 1
 tossNo += 1

print "The coin landed on tails " + str(tails) + " times \n"
print "The coin landed on heads " + str(heads) + " times \n"

--
ATTEMPT 2
--
import random

heads = 0
tails = 0
tossNo = 0

while tossNo <= 99:
if random.randint(1,2) == 1:
heads += 1
tossNo += 1
elif random.randint(1,2) == 2:
 tails += 1
 tossNo += 1

print "The coin landed on tails " + str(tails) + " times \n"
print "The coin landed on heads " + str(heads) + " times \n"

  
If your purpose was really to "give a name to a function," you can do 
that by:


toss = random.randint

Notice that we do *not* include the parentheses.  You want to call the 
function (by whatever name) inside the loop.  So change it to


while tossNo <= 99:
   if toss(1,2) == 1:
   heads += 1
   tossNo += 1


I have no idea why you have an elif clause in there.

DaveA

___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Giving a name to a function and calling it, rather than calling the function directly

2010-09-04 Thread Alex Hall
On 9/4/10, lists  wrote:
> Hi folks,
>
> I'm new to Python, I'm working my way through some intro books, and I
> have a question that I wonder if someone could help me with please?
>
> This is my attempt at solving an exercise where the program is
> supposed to flip a coin 100 times and then tell you the number of
> heads and tails.
>
> ATTEMPT 1 returns:
>
> The coin landed on tails 100 times
>
> The coin landed on heads 0 times
>
> ATTEMPT 2 returns:
>
> The coin landed on tails 75 times
>
> The coin landed on heads 25 times
>
> I expected to see the result in attempt 2. I don't fully understand
> why the results are different however. Is it because Python only runs
> the randint function once when I call it by the name I assigned to it
> in attempt 1, but it runs the function fully on each iteration of the
> loop in attempt 2? Why are these two things different?
Exactly. Essentially when you say
x=random.randint(1,2)
you are putting the value returned by randint into x, and this happens
only once. Had you moved that assignment into the while loop it would
keep replacing x, or toss in your case, with a random integer, but
because you just call it once it is only assigned once. Python, or any
language, would have no way of knowing that you want to reassign toss
each time. Loops are used to repeat actions, but you left the
assignment of your random int outside of the loop in attempt1 and so
there is no way for Python to know that you actually want toss updated
100 times. I hope I explained this okay.
>
> Thanks in advance,
>
> Chris
> --
> ATTEMPT 1
> --
> import random
>
> heads = 0
> tails = 0
> tossNo = 0
> toss = random.randint(1,2)
>
> while tossNo <= 99:
> if toss == 1:
> heads += 1
> tossNo += 1
> elif toss == 2:
>  tails += 1
>  tossNo += 1
>
> print "The coin landed on tails " + str(tails) + " times \n"
> print "The coin landed on heads " + str(heads) + " times \n"
>
> --
> ATTEMPT 2
> --
> import random
>
> heads = 0
> tails = 0
> tossNo = 0
>
> while tossNo <= 99:
> if random.randint(1,2) == 1:
> heads += 1
> tossNo += 1
> elif random.randint(1,2) == 2:
>  tails += 1
>  tossNo += 1
>
> print "The coin landed on tails " + str(tails) + " times \n"
> print "The coin landed on heads " + str(heads) + " times \n"
> ___
> Tutor maillist  -  Tutor@python.org
> To unsubscribe or change subscription options:
> http://mail.python.org/mailman/listinfo/tutor
>


-- 
Have a great day,
Alex (msg sent from GMail website)
mehg...@gmail.com; http://www.facebook.com/mehgcap
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


[Tutor] Giving a name to a function and calling it, rather than calling the function directly

2010-09-04 Thread lists
Hi folks,

I'm new to Python, I'm working my way through some intro books, and I
have a question that I wonder if someone could help me with please?

This is my attempt at solving an exercise where the program is
supposed to flip a coin 100 times and then tell you the number of
heads and tails.

ATTEMPT 1 returns:

The coin landed on tails 100 times

The coin landed on heads 0 times

ATTEMPT 2 returns:

The coin landed on tails 75 times

The coin landed on heads 25 times

I expected to see the result in attempt 2. I don't fully understand
why the results are different however. Is it because Python only runs
the randint function once when I call it by the name I assigned to it
in attempt 1, but it runs the function fully on each iteration of the
loop in attempt 2? Why are these two things different?

Thanks in advance,

Chris
--
ATTEMPT 1
--
import random

heads = 0
tails = 0
tossNo = 0
toss = random.randint(1,2)

while tossNo <= 99:
if toss == 1:
heads += 1
tossNo += 1
elif toss == 2:
 tails += 1
 tossNo += 1

print "The coin landed on tails " + str(tails) + " times \n"
print "The coin landed on heads " + str(heads) + " times \n"

--
ATTEMPT 2
--
import random

heads = 0
tails = 0
tossNo = 0

while tossNo <= 99:
if random.randint(1,2) == 1:
heads += 1
tossNo += 1
elif random.randint(1,2) == 2:
 tails += 1
 tossNo += 1

print "The coin landed on tails " + str(tails) + " times \n"
print "The coin landed on heads " + str(heads) + " times \n"
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor