Re: [Tutor] list, tuple or dictionary

2011-11-29 Thread Steven D'Aprano

ADRIAN KELLY wrote:

i am trying to create a program that will allow users to enter items and their 
prices; should i be looking at a list, tuple or what?
many thanksadrian



Translated to a version more familiar in the "real world":

   "I'm looking to build a wooden wardrobe that will allow
the user to store their clothes. Should I be using a saw,
a hammer, a drill, or what?"

The only correct answer is "Yes you should."

Lists, tuples and dicts are all basic tools in your programming toolbox, you 
should ALWAYS be looking at using them. But you use them for different purposes.


Perhaps if you narrow your question down to something more specific we can 
give a more useful answer.


Or... just try it! Don't be scared to write some code to throw it away. 
Especially when learning, there is no better way to learn than to write some 
code, discover what you can and can't do with the tools, learn the limitations 
by trying it, and then using that knowledge to write better code.



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


Re: [Tutor] list, tuple or dictionary

2011-11-29 Thread ADRIAN KELLY

Sound Wayne, thank you

 

 

From: waynejwer...@gmail.com
Date: Tue, 29 Nov 2011 15:11:46 -0600
Subject: Re: [Tutor] list, tuple or dictionary
To: kellyadr...@hotmail.com
CC: tutor@python.org

On Tue, Nov 29, 2011 at 3:04 PM, ADRIAN KELLY  wrote:







thanks guy, i was thinking of using a dictionary:- Stock_list = {"White Bread": 
1.24,"Biscuits": 1.77,"Banana" : 0.23,"Tea 
Bags" : 2.37,

"Eggs" : 1.23,"Beans" : 0.57}
how would i go about adding, for example tea and eggs to get a subtotal?


Why, you would add tea and eggs, of course!
print("Subtotal: ", Stock_list["Tea Bags"] + Stock_list["Eggs"]) 


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


Re: [Tutor] list, tuple or dictionary

2011-11-29 Thread Wayne Werner
On Tue, Nov 29, 2011 at 3:04 PM, ADRIAN KELLY wrote:

>  thanks guy, i was thinking of using a dictionary:-
>  Stock_list = {"White Bread": 1.24,
> "Biscuits": 1.77,
> "Banana" : 0.23,
> "Tea Bags" : 2.37,
> "Eggs" : 1.23,
> "Beans" : 0.57}
>
> how would i go about *adding, *for example tea and eggs to get a subtotal?
>

Why, you would add tea and eggs, of course!

print("Subtotal: ", Stock_list["Tea Bags"] + Stock_list["Eggs"])


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


Re: [Tutor] list, tuple or dictionary

2011-11-29 Thread ADRIAN KELLY

thanks guy, i was thinking of using a dictionary:- Stock_list = {"White Bread": 
1.24,"Biscuits": 1.77,"Banana" : 0.23,"Tea 
Bags" : 2.37,"Eggs" : 1.23,"Beans" : 0.57}
how would i go about adding, for example tea and eggs to get a subtotal? 

  

Adrian Kelly 
1 Bramble Close

Baylough

Athlone

County Westmeath

0879495663


From: waynejwer...@gmail.com
Date: Tue, 29 Nov 2011 14:49:00 -0600
Subject: Re: [Tutor] list, tuple or dictionary
To: kellyadr...@hotmail.com
CC: tutor@python.org

On Tue, Nov 29, 2011 at 2:31 PM, ADRIAN KELLY  wrote:







i am trying to create a program that will allow users to enter items and their 
prices; should i be looking at a list, tuple or what?
The entering part isn't as important as how you want to display the data. For 
instance, here's a program that allows the user to input an unlimited amount of 
data (using Python 3.x):


while input("Enter q to quit, or an item: ").lower() not in ('q', 'quit', 
'goodbye'):

 input("Enter the price: ")
Of course it doesn't store the data, so it's pretty useless. But it does allow 
the user to input whatever they want.


If you wanted to simply create a collection of items you could do it as a list 
with alternating values:


inventory = ['Crunchy Frog', 4.13, 'Anthrax Ripple', 12.999, 
'Spring Surprise', 0.00]

for x in range(0, len(inventory)-1, 2):  print(inventory[x], 
inventory[x+1])
Or as a list of tuples:  

inventory = [('Norwegian Blue', 500.00), ('Slug', 500.00), ('Cage', 50.00)] 
   for item in inventory:print(item[0], item[1])
Or a dictionary:


inventory = {'Spam':5.00, 'Spam on eggs':10.00, 'Spam on Spam':7.50}for 
item, price in inventory.items():print(item, price)


Or if you wanted to get ridiculous, you could go with a list of classes:
class Item:def __init__(self, desc='', price=0.00):self.desc = desc

self.price = pricedef __repr__(self):return str(self)
def __str__(self):return "{0} - {1}".format(self.desc, self.price)


inventory = [Item('Lumberjack', 5.5), Item('Tree', 50), Item('Flapjack', 
0.5)]for item in inventory:print(item)

It just depends on how complex you want to get!

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


Re: [Tutor] list, tuple or dictionary

2011-11-29 Thread Wayne Werner
On Tue, Nov 29, 2011 at 2:31 PM, ADRIAN KELLY wrote:

>  i am trying to create a program that will allow users to enter items and
> their prices; should i be looking at a list, tuple or what?
>

The entering part isn't as important as how you want to display the data.
For instance, here's a program that allows the user to input an unlimited
amount of data (using Python 3.x):

while input("Enter q to quit, or an item: ").lower() not in ('q', 'quit',
'goodbye'):
 input("Enter the price: ")

Of course it doesn't store the data, so it's pretty useless. But it does
allow the user to input whatever they want.

If you wanted to simply create a collection of items you could do it as a
list with alternating values:

inventory = ['Crunchy Frog', 4.13, 'Anthrax Ripple', 12.999,
'Spring Surprise', 0.00]
for x in range(0, len(inventory)-1, 2):
  print(inventory[x], inventory[x+1])

Or as a list of tuples:

inventory = [('Norwegian Blue', 500.00), ('Slug', 500.00), ('Cage',
50.00)]
for item in inventory:
print(item[0], item[1])

Or a dictionary:

inventory = {'Spam':5.00, 'Spam on eggs':10.00, 'Spam on Spam':7.50}
for item, price in inventory.items():
print(item, price)

Or if you wanted to get ridiculous, you could go with a list of classes:

class Item:
def __init__(self, desc='', price=0.00):
self.desc = desc
self.price = price
def __repr__(self):
return str(self)
def __str__(self):
return "{0} - {1}".format(self.desc, self.price)

inventory = [Item('Lumberjack', 5.5), Item('Tree', 50), Item('Flapjack',
0.5)]
for item in inventory:
print(item)


It just depends on how complex you want to get!
HTH,
Wayne
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] list, tuple or dictionary

2011-11-29 Thread bodsda
You could use any of them, but a dict would be the most logical assuming no 
duplicate items

Bodsda 
Sent from my BlackBerry® wireless device

-Original Message-
From: ADRIAN KELLY 
Sender: tutor-bounces+bodsda=googlemail@python.org
Date: Tue, 29 Nov 2011 20:31:56 
To: 
Subject: [Tutor] list, tuple or dictionary

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

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


[Tutor] list, tuple or dictionary

2011-11-29 Thread ADRIAN KELLY

i am trying to create a program that will allow users to enter items and their 
prices; should i be looking at a list, tuple or what?
many thanksadrian

 

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


Re: [Tutor] list of objects?

2011-11-16 Thread bob gailer
Please always reply-all so a copy goes to the list. Am forwarding this 
on your behalf.


I will reply this afternoon.

On 11/16/2011 7:18 AM, Elwin Estle wrote:
Part of the reason I am writing this program is to learn OOP, hence 
the use of classes.  Most of what little programming background I have 
comes from working with various flavors of BASIC on old Atari 8-bit 
computers back in the day, and more recently a little Tcl/Tk, so my 
first instinct is to do everything from a procedural standpoint.  I'm 
trying to get out of my comfort zone.


As for the game, I am doing the 'easy' version of spider that uses 8 
suits of spades.  I was planing to just re-draw the display after each 
move.  Input-wise, I was just going to use raw_input.  My idea was to 
have a move consist of a three character coordinate, The 10 dealt 
piles would be named by letter, A-J, and the cards in each pile would 
be by number, i.e. 1-nn.  A move would consist of the starting pile, 
the number of the card in that pile, and the letter of the destination 
pile, so 'B5H' would move everything from the 5th card down in pile B 
and put it on pile H.



*From:* bob gailer 
*To:* Elwin Estle 
*Cc:* "tutor@python.org" 
*Sent:* Tuesday, November 15, 2011 9:18 PM
*Subject:* Re: [Tutor] list of objects?

On 11/15/2011 8:40 AM, Elwin Estle wrote:

I am attempting to write a text based spider solitaire game.


What are the rules of your version of Spider? The only spiders I know 
have 10 dealt piles and 1 draw pile.


I think you have greatly complicated things by using classes. Consider:

deck = random.shuffle(range(13)*8) # list of 108 card "indexes" in 
random order.

values = "A23456789JQK" # display values corresponding to indexes
piles = [deck[x:x+10] for x in range(0,108,10)]

Anytime you want to display the value of a card use values[cardIndex]
for example to display the last card in each pile:

for pile in piles:
  print values[pile[-1]],

What will your actual display look llike?

Will you completely reprint it after each move, or alter it in place?

How will you get the moves from the player?
--
Bob Gailer
919-636-4239
Chapel Hill NC





--
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] list of objects?

2011-11-15 Thread bob gailer

On 11/15/2011 8:40 AM, Elwin Estle wrote:

I am attempting to write a text based spider solitaire game.


What are the rules of your version of Spider? The only spiders I know 
have 10 dealt piles and 1 draw pile.


I think you have greatly complicated things by using classes. Consider:

deck = random.shuffle(range(13)*8) # list of 108 card "indexes" in 
random order.

values = "A23456789JQK" # display values corresponding to indexes
piles = [deck[x:x+10] for x in range(0,108,10)]

Anytime you want to display the value of a card use values[cardIndex]
for example to display the last card in each pile:

for pile in piles:
  print values[pile[-1]],

What will your actual display look llike?

Will you completely reprint it after each move, or alter it in place?

How will you get the moves from the player?

--
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] list of objects?

2011-11-15 Thread James Reynolds
On Tue, Nov 15, 2011 at 8:40 AM, Elwin Estle wrote:

> I am attempting to write a text based spider solitaire game.  I have  a
> pretty simple card class, and a deck class, which has a list of card
> objects, which are shuffled, then individual elements are put into
> self.dealt, which is a 'list of lists' when the cards are dealt.
>
> I am trying to control the visibility of the cards.  There is a small
> "for" loop in the "deal" method of the deck class, this is intended to
> toggle the visibility of four of the cards.  It does that just fine, but
> for some reason, it seems to be randomly toggling the visibility of other
> cards in the self.dealt list and I am thoroughly confused as to why that
> is.  Is it something to do with the way objects are referenced?  Is my list
> of card objects a bad way to approach this?
>
> ___
> Tutor maillist  -  Tutor@python.org
> To unsubscribe or change subscription options:
> http://mail.python.org/mailman/listinfo/tutor
>
>


A few thoughts first:

class Card(object):

def __init__(self):
self.value = ''
self.display = 'X'

I would change the above to:

class Card(object):

def __init__(self, value):
self.value = value
self.display = 'X'

(because you always have a card with a value)

Which allows you to save a line here:

for value in values:
card = Card(value)
card_list.append(card)

like that

Another idea would be to use "extend" here:

values = []

for i in range(1, 11):
values.append(str(i))

values.append('J')
values.append('Q')
values.append('K')

So, you would do something like this instead:

mylist = range(1, 11)
mylist.extend(['J', 'Q', 'K'])

for i in mylist:
values.append(str(i))

What extend does is it extends one list with another list.

Also, you can build the string conversion into the card class:

Further saving you the above loop:

class Card(object):

def __init__(self, value):
self.value = str(value)
self.display = 'X'

and then in the create_cards def:

mylist = range(1, 11)
mylist.extend(['J', 'Q', 'K'])

#for i in mylist:
#values.append(str(i))

for value in mylist:
card = Card(value)
card_list.append(card)


(as an aside, I'm not sure why you do this:

card_list = card_list * 8

if you need two decks, I think you should have a variable like 4*decks so
you can shuffle the right amount of decks)

I don't think you need to shuffle twice here (which in turn calls into
question why you need a separate method, but maybe you were going to build
on it - i do that all the time):

def shuffle(self):
random.shuffle(self.cards)
#random.shuffle(self.cards)


Now onto your question:

You can see that there are four card values that are shown visible in any
given run. There are always four values and they are always random from run
to run.

If you comment out this loop

#for index, card in enumerate(self.dealt[5]):
#print index, card
#self.dealt[5][index].display  = self.dealt[5][index].value

You won't get that anymore.

If you want to control whether to display any particular card or not, I
would add a variable to the display_cards method:

def display_cards(self, display = True):

for row in self.dealt:
for card in row:
if display:
print '%5s ' % card.display,
else:
print '%5s ' % card.value,
print ''

Or you can add another value to the card class, if you want to control the
display of cards on a unique basis:

class Card(object):

def __init__(self, value):
self.value = str(value)
self.display = 'X'
self.display_or_value = True

then you can change your method above to be:

def display_cards(self):

for row in self.dealt:
for card in row:
if card.display_or_value:
print '%5s ' % card.display,
else:
print '%5s ' % card.value,
print ''


Long story short, if I wanted to control the visibility of any card, I
would do it within the Card class (since presumably that is an attribute of
any given card - think about it in real life, a card can be up, or a card
can be down, yet it still retains its other properties, like color, value,
creases, etc)
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] list of objects?

2011-11-15 Thread Walter Prins
Hi Elwin,

On 15 November 2011 13:40, Elwin Estle  wrote:

> I am attempting to write a text based spider solitaire game.  I have  a
> pretty simple card class, and a deck class, which has a list of card
> objects, which are shuffled, then individual elements are put into
> self.dealt, which is a 'list of lists' when the cards are dealt.
>
> I am trying to control the visibility of the cards.  There is a small
> "for" loop in the "deal" method of the deck class, this is intended to
> toggle the visibility of four of the cards.  It does that just fine, but
> for some reason, it seems to be randomly toggling the visibility of other
> cards in the self.dealt list and I am thoroughly confused as to why that
> is.  Is it something to do with the way objects are referenced?  Is my list
> of card objects a bad way to approach this?
>

Off the top of my head, your problem is likely due to the line that reads:
card_list = card_list * 8

What this will do is put the *same* set of card objects in the list to
begin with, into a new card_list 8 times over.  So the *same* Jack (for
example) will appear 8 times in the resulting list.

This list, card_list, is the list that implements then later on sliced in
your deal method.  So, when you then set the cards in the dealt hand to
visible in your self.dealt[5] loop, because these same cards (card objects)
also are part of the other piles/hands, they also appear visible elsewhere
when the display method is called.

To fix: Replace the line above (e.g. card_list = card_list * 8)  with
something that explicitly constructs new cards 8 times, thereby not holding
mutliple refernces from seperate piles to the same card, then you should
have no further issues.  Maybe loop 8 times and make a function of te
preceding code etc.

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


[Tutor] list of objects?

2011-11-15 Thread Elwin Estle
I am attempting to write a text based spider solitaire game.  I have  a pretty 
simple card class, and a deck class, which has a list of card objects, which 
are shuffled, then individual elements are put into self.dealt, which is a 
'list of lists' when the cards are dealt.

I am trying to control the visibility of the cards.  There is a small "for" 
loop in the "deal" method of the deck class, this is intended to toggle the 
visibility of four of the cards.  It does that just fine, but for some reason, 
it seems to be randomly toggling the visibility of other cards in the 
self.dealt list and I am thoroughly confused as to why that is.  Is it 
something to do with the way objects are referenced?  Is my list of card 
objects a bad way to approach this?
import random

class Card(object):

def __init__(self):
self.value = ''
self.display = 'X'

class Deck(object):

def __init__(self):
self.cards = self.create_cards()
self.shuffle()
self.dealt = []
self.draw_piles = []
self.deal()

def create_cards(self):

card_list = []

values = []

for i in range(1, 11):
values.append(str(i))

values.append('J')
values.append('Q')
values.append('K')

for value in values:
card = Card()
card.value = value
card_list.append(card)

card_list = card_list * 8
  
return card_list

def shuffle(self):
random.shuffle(self.cards)
random.shuffle(self.cards)


def deal(self):

self.dealt.append(self.cards[0:10])
self.dealt.append(self.cards[10:20])
self.dealt.append(self.cards[20:30])
self.dealt.append(self.cards[30:40])
self.dealt.append(self.cards[40:50])
self.dealt.append(self.cards[50:54])

self.draw_piles.append(self.cards[54:64])
self.draw_piles.append(self.cards[64:74])
self.draw_piles.append(self.cards[74:84])
self.draw_piles.append(self.cards[84:94])
self.draw_piles.append(self.cards[94:105])

for index, card in enumerate(self.dealt[5]):
self.dealt[5][index].display  = self.dealt[5][index].value


def display_cards(self):

for row in self.dealt:
for card in row:
print '%5s ' % card.display,
print ''


mydeck = Deck()

mydeck.display_cards()



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


Re: [Tutor] List of Classes with a dictionary within the Class.

2011-09-21 Thread Mukund Chavan

That worked. Thank you for the explanation. 

I was trying to take a list of these objects and insert it as a part of a mongo 
document using the pymongo package. 

But based on what your input and little more reading up, I can use the 
"__dict__" method to accomplish the same.

Thanks again.

- Mukund


> Date: Thu, 22 Sep 2011 10:58:09 +1000
> From: st...@pearwood.info
> To: tutor@python.org
> Subject: Re: [Tutor] List of Classes with a dictionary within the Class.
> 
> Mukund Chavan wrote:
> > Hi,
> > 
> > I was trying to get a list of Class Objects. 
> > The Class itself has string fields and a dictionary that is initialized as 
> > a part of the "__init__"
> 
> No it doesn't. It has a dictionary that is initialised *once*, when the 
> class is defined. From that point on, every instance just modifies the 
> same shared dictionary:
> 
> > class Person(object):
> >"""__init__() functions as the class constructor"""
> >personAttrs={"'num1":"","num1":""}
> 
> This is a "class attribute", stored in the class itself, and shared 
> between all instances.
> 
> 
> >def __init__(self, name=None, job=None, quote=None, num1=None, 
> > num2=None):
> >   self.name = name
> >   self.job = job
> >   self.quote = quote
> >   self.personAttrs["num1"]=num1
> >   self.personAttrs["num2"]=num2
> 
> This merely modifies the existing class attribute. You want something 
> like this instead:
> 
> class Person(object):
>  def __init__(self, name=None, job=None, quote=None,
>   num1=None, num2=None
>  ):
>  self.name = name
>  self.job = job
>  self.quote = quote
>  self.personAttrs = {'num1': num1, 'num2': num2}
> 
> This creates a new dictionary for each Person instance.
> 
> But why are you doing it that way? Each Person instance *already* has 
> its own instance dictionary for storing attributes. You don't need to 
> manage it yourself -- just use ordinary attributes, exactly as you do 
> for name, job, and quote.
> 
> class Person(object):
>  def __init__(self, name=None, job=None, quote=None,
>   num1=None, num2=None
>  ):
>  self.name = name
>  self.job = job
>  self.quote = quote
>  self.num1 = num1
>  self.num2 = num2
> 
> 
> 
> -- 
> Steven
> ___
> Tutor maillist  -  Tutor@python.org
> To unsubscribe or change subscription options:
> http://mail.python.org/mailman/listinfo/tutor
  ___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] List of Classes with a dictionary within the Class.

2011-09-21 Thread Steven D'Aprano

Mukund Chavan wrote:

Hi,

I was trying to get a list of Class Objects. 
The Class itself has string fields and a dictionary that is initialized as a part of the "__init__"


No it doesn't. It has a dictionary that is initialised *once*, when the 
class is defined. From that point on, every instance just modifies the 
same shared dictionary:



class Person(object):
   """__init__() functions as the class constructor"""
   personAttrs={"'num1":"","num1":""}


This is a "class attribute", stored in the class itself, and shared 
between all instances.




   def __init__(self, name=None, job=None, quote=None, num1=None, num2=None):
  self.name = name
  self.job = job
  self.quote = quote
  self.personAttrs["num1"]=num1
  self.personAttrs["num2"]=num2


This merely modifies the existing class attribute. You want something 
like this instead:


class Person(object):
def __init__(self, name=None, job=None, quote=None,
 num1=None, num2=None
):
self.name = name
self.job = job
self.quote = quote
self.personAttrs = {'num1': num1, 'num2': num2}

This creates a new dictionary for each Person instance.

But why are you doing it that way? Each Person instance *already* has 
its own instance dictionary for storing attributes. You don't need to 
manage it yourself -- just use ordinary attributes, exactly as you do 
for name, job, and quote.


class Person(object):
def __init__(self, name=None, job=None, quote=None,
 num1=None, num2=None
):
self.name = name
self.job = job
self.quote = quote
self.num1 = num1
self.num2 = num2



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


[Tutor] List of Classes with a dictionary within the Class.

2011-09-21 Thread Mukund Chavan

Hi,

I was trying to get a list of Class Objects. 
The Class itself has string fields and a dictionary that is initialized as a 
part of the "__init__"

However the fields of the dictionary for each object in the list of class 
objects seems to be the same.
I took an example from the following site:
"http://www.daniweb.com/software-development/python/code/216631"; and modified 
it. The code is cut/pasted below
with the result of the run immediately following. I expected the 4th and 5th 
column in the output to be unique, but
they seem to get the value of the last item in the iter range. 

I am running "Python 2.6.5" on Ubuntu 10.04 TLS-64bit.

Thanks in advance.

- Mukund


Code:

#!/usr/bin/python

#a list of class objects to mimic a C type array of structures
# tested with Python24 vegaseat 30sep2005

class Person(object):
   """__init__() functions as the class constructor"""
   personAttrs={"'num1":"","num1":""}
   def __init__(self, name=None, job=None, quote=None, num1=None, num2=None):
  self.name = name
  self.job = job
  self.quote = quote
  self.personAttrs["num1"]=num1
  self.personAttrs["num2"]=num2

print

# make a list of class Person(s)
personList = []
for i in range(4):
personList.append(Person("M",i,"XYZ",-i,i))

print "Show one particular item:"
print personList[0].name

print


print "... then show all quotes and who said so:"
for person in personList:
   print "\"%s\" %s (%s) %s %s" % (person.quote, person.name, 
person.job,str(person.personAttrs['num1']),str(person.personAttrs['num2']))

print


print "What the heck did the person named Sanosi say?"
look = "Sanosi"
for person in personList:
   if look in person.name:
  print "%s: \"%s\"" % (person.name, person.quote)



Output:

Show one particular item:
M

... then show all quotes and who said so:
"XYZ" M (0) -3 3
"XYZ" M (1) -3 3
"XYZ" M (2) -3 3
"XYZ" M (3) -3 3

What the heck did the person named Sanosi say?


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


[Tutor] List of lists optimization and printing.

2011-07-29 Thread Sergey
Hello.

Yes, catb.org and so on.
I was searching for some kind of finding max width in a table (a list of two
lists) and had found this mailing list.
So I want somebody to look at my code and say what can be done better from a
programmer point of view.
Just SQL like printing and writing.
I mean optimization.
I always want to know what is the best way. Thanks.
* I don't know is it good to paste 62 lines there so here's the pastie
http://pastie.org/2291721
I hope it will be monospaced.^U
I know about SQLAlchemy but I just want to have my data in plain text because I
can't find good cross-platform suites to keep contacts, many contacts. I mean
phone number, name and so on. Something for a little bit entertprise tasks.
Yes.
Thanks.
Debian bleeding edge.
Python 2.6 default. And 2.7, 3.2 too.

Site: site
Login: login
Password: password
[['site', 'login', 'password']]
[4, 5, 8]
+--+---+--+
| Site | Login | Password |
+--+---+--+
| site | login | password |
+--+---+--+


South Africas premier free email service - www.webmail.co.za 

Save on insurance with OUTsurance
https://www.outsurance.co.za/insurance-quote/?source=webmailmailer&cr=facp11_468x60&cid=221


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


Re: [Tutor] List problem

2011-07-25 Thread Peter Otten
David Merrick wrote:

> def append(self,item):
>  '''Adds an item to the end of the List'''
> 
>  current = self.head
>  previous = None
>  while current.getNext() != None:
>  previous = current
>  current = current.getNext()
>  if current.getNext() == None:
>  previous  = previous.setNext(current)
>  current = current.setNext(item)

> myList.append(24)

Your append() method expects item to be a Node instance, so you have to wrap 
your data (24 in the example) into a Node

myList.append(Node(24))

or modify append() accordingly. Note that there is at least one other 
problem with your append() implementation: you cannot append to an empty 
UnorderedList because you don't handle the case where self.head is None.

Stylistically your code looks like a literal translation from Java; in 
Python it is good practice to avoid getter/setter methods and use attributes 
(or properties) instead. Also, we have a cool way to implement iteration: 
generators.

#untested
class UnorderedList(object):
def __iter__(self):
current = self.head
while current is not None:
yield current.data

You can then write

print 24 in myList

instead of

print myList.search(24)

In idiomatic Python you'd call the length() method __len__() and invoke it 
as

print len(myList)

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


Re: [Tutor] List problem

2011-07-24 Thread Andre Engels
On Mon, Jul 25, 2011 at 4:19 AM, David Merrick  wrote:


> def append(self,item):
>  '''Adds an item to the end of the List'''
>
>  current = self.head
>  previous = None
>  while current.getNext() != None:
>  previous = current
>  current = current.getNext()
>  if current.getNext() == None:
>  previous  = previous.setNext(current)
>  current = current.setNext(item)
>

current is here the first element of your list. This element does not have a
getNext() method. Instead, if you want to use this system, you'll have to
use a (probably re-defined) getNext() method of your list class itself.

-- 
André Engels, andreeng...@gmail.com
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] List problem

2011-07-24 Thread bob gailer
I have no desire to wade through all that code. Please post the entire 
traceback.



On 7/24/2011 10:19 PM, David Merrick wrote:

class Node:
def __init__(self,initdata):
self.data = initdata
self.next = None

def getData(self):
return self.data

def getNext(self):
return self.next

def setdata(self,newData):
self.data = newData

def setNext(self,newnext):
   self.next = newnext

class UnorderedList:

def __init__(self):
self.head = None

def isEmpty(self):
return self.head == None

## Adds next item on to the head
def add(self,item):
temp = Node(item)
temp.setNext(self.head)
self.head = temp

def length(self):
current = self.head
count = 0
while current !=None:
count = count + 1
current = current.getNext()
return count

def search(self,item):
current = self.head
found = False
while current != None and not found:
if current.getData()== item:
found =True
else:
current = current.getNext()
return found


def remove(self,item):
'''Removes item from the List'''

current = self.head
previous = None
found = False
while not found:
if current.getData() == item:
found = True
else:
previous = current
current = current.getNext()
if previous == None:
self.head = current.getNext()
else:
previous.setNext(current.getNext())

def getIndex(self,item):
current = self.head
index = 0
found = False
while current != None and not found:
if current.getData()== item:
found = True
else:
current = current.getNext()
index = index + 1
return index

def append(self,item):
 '''Adds an item to the end of the List'''

 current = self.head
 previous = None
 while current.getNext() != None:
 previous = current
 current = current.getNext()
 if current.getNext() == None:
 previous  = previous.setNext(current)
 current = current.setNext(item)


myList = UnorderedList()
myList.add(31)
myList.add(77)
myList.add(17)
myList.add(93)
myList.add(26)
myList.add(54)
print(myList.length())
myList.append(24)
print(myList.length())
myList.search(24)

Output

Python 3.1 (r31:73574, Jun 26 2009, 20:21:35) [MSC v.1500 32 bit (Intel)]
Type "help", "copyright", "credits" or "license" for more information.
>>> [evaluate unorderedList.py]
6
builtins.AttributeError: 'int' object has no attribute 'getNext'
>>>

What do I need to do the append method to fix it?

--
Dave Merrick

merrick...@gmail.com 

Ph   03 3423 121
Cell 027 3089 169


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



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


[Tutor] List problem

2011-07-24 Thread David Merrick
class Node:
def __init__(self,initdata):
self.data = initdata
self.next = None

def getData(self):
return self.data

def getNext(self):
return self.next

def setdata(self,newData):
self.data = newData

def setNext(self,newnext):
   self.next = newnext

class UnorderedList:

def __init__(self):
self.head = None

def isEmpty(self):
return self.head == None

## Adds next item on to the head
def add(self,item):
temp = Node(item)
temp.setNext(self.head)
self.head = temp

def length(self):
current = self.head
count = 0
while current !=None:
count = count + 1
current = current.getNext()
return count

def search(self,item):
current = self.head
found = False
while current != None and not found:
if current.getData()== item:
found =True
else:
current = current.getNext()
return found


def remove(self,item):
'''Removes item from the List'''

current = self.head
previous = None
found = False
while not found:
if current.getData() == item:
found = True
else:
previous = current
current = current.getNext()
if previous == None:
self.head = current.getNext()
else:
previous.setNext(current.getNext())

def getIndex(self,item):
current = self.head
index = 0
found = False
while current != None and not found:
if current.getData()== item:
found = True
else:
current = current.getNext()
index = index + 1
return index

def append(self,item):
 '''Adds an item to the end of the List'''

 current = self.head
 previous = None
 while current.getNext() != None:
 previous = current
 current = current.getNext()
 if current.getNext() == None:
 previous  = previous.setNext(current)
 current = current.setNext(item)


myList = UnorderedList()
myList.add(31)
myList.add(77)
myList.add(17)
myList.add(93)
myList.add(26)
myList.add(54)
print(myList.length())
myList.append(24)
print(myList.length())
myList.search(24)

Output

Python 3.1 (r31:73574, Jun 26 2009, 20:21:35) [MSC v.1500 32 bit (Intel)]
Type "help", "copyright", "credits" or "license" for more information.
>>> [evaluate unorderedList.py]
6
builtins.AttributeError: 'int' object has no attribute 'getNext'
>>>

What do I need to do the append method to fix it?

-- 
Dave Merrick

merrick...@gmail.com

Ph   03 3423 121
Cell 027 3089 169
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] List methods inside a dictionary of list

2011-07-11 Thread Rafael Turner
I did not understand the behavior of array multiplication. In fact, I
just now learned what it was called thanks to your email.

Best wishes,
Rafael

On Mon, Jul 11, 2011 at 9:33 AM, Brett Ritter  wrote:
> On Mon, Jul 11, 2011 at 9:26 AM, Rafael Turner
>  wrote:
>> I am playing lists and dictionaries and I came across this
>> counter-intuitive result.
>>
> d = dict(zip(['a', 'q', 'c', 'b', 'e', 'd', 'g', 'j'],8*[[0]]))
> ...
> d['a'].__setitem__(0,4)
> ...
>>
>> I was not expecting all the keys to be updated. Is there any
>> documentation I could read on how different datatypes' methods and
>> operators interact differently when inside a dictionary?  I would also
>> like to find a way of being able to use list methods in side a
>> dictionary so that
>
> As has been mentioned, this isn't the dictionary doing anything weird,
> this is that "8*[[0]]" gives you a list of 8 references to the same
> list.  You can play with just that part and see that that's the source
> of your issue.
>
> To achieve what you are trying, try this instead:
>
> d = dict([(x,[0]) for x in ['a', 'q', 'c', 'b', 'e', 'd', 'g', 'j']])
>
> Can you understand how this behaves differently than 8*[[0]] ?  Check
> the Python docs for array multiplication if you're confused, but the
> basic idea is that "[0]" isn't getting evaluated freshly for every
> piece in the array for 8*[[0]], but in a list comprehension it is.
> --
> Brett Ritter / SwiftOne
> swift...@swiftone.org
>
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] List methods inside a dictionary of list

2011-07-11 Thread Brett Ritter
On Mon, Jul 11, 2011 at 9:26 AM, Rafael Turner
 wrote:
> I am playing lists and dictionaries and I came across this
> counter-intuitive result.
>
 d = dict(zip(['a', 'q', 'c', 'b', 'e', 'd', 'g', 'j'],8*[[0]]))
...
 d['a'].__setitem__(0,4)
...
>
> I was not expecting all the keys to be updated. Is there any
> documentation I could read on how different datatypes' methods and
> operators interact differently when inside a dictionary?  I would also
> like to find a way of being able to use list methods in side a
> dictionary so that

As has been mentioned, this isn't the dictionary doing anything weird,
this is that "8*[[0]]" gives you a list of 8 references to the same
list.  You can play with just that part and see that that's the source
of your issue.

To achieve what you are trying, try this instead:

d = dict([(x,[0]) for x in ['a', 'q', 'c', 'b', 'e', 'd', 'g', 'j']])

Can you understand how this behaves differently than 8*[[0]] ?  Check
the Python docs for array multiplication if you're confused, but the
basic idea is that "[0]" isn't getting evaluated freshly for every
piece in the array for 8*[[0]], but in a list comprehension it is.
-- 
Brett Ritter / SwiftOne
swift...@swiftone.org
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] List methods inside a dictionary of list

2011-07-11 Thread Walter Prins
Hi,

On 11 July 2011 14:26, Rafael Turner  wrote:

>
> >>> d = dict(zip(['a', 'q', 'c', 'b', 'e', 'd', 'g', 'j'],8*[[0]]))
> >>>d
> Out:
> {'a': [0],
>  'b': [0],
>  'c': [0],
>  'd': [0],
>  'e': [0],
>  'g': [0],
>  'j': [0],
>  'q': [0]}
>
> >>> d['a'].__setitem__(0,4)
> >>> d
> Out:
> {'a': [4],
>  'b': [4],
>  'c': [4],
>  'd': [4],
>  'e': [4],
>  'g': [4],
>  'j': [4],
>  'q': [4]}
>
> I was not expecting all the keys to be updated. Is there any
> documentation I could read on how different datatypes' methods and
> operators interact differently when inside a dictionary?  I would also
> like to find a way of being able to use list methods in side a
> dictionary so that
>

There's no funny interaction based on datatypes as you imply.  The thing
you're missing is that when you do 8*[[0]], you're actually creating a a
list of references to another **single list** (which happens to contain a
single value, 0.)  Thus, when you then update that single value 0 in that
single list, being pointed to by the several locations in the outer list,
you predictably end up seeing the change from all the references in the
outer list.

To illustrate, do the following:
>>> l=[0]
>>> l2=[l]
>>> l2
[[0]]
>>> l3=8*l2
>>> l3
[[0], [0], [0], [0], [0], [0], [0], [0]]
>>> l[0]=1
>>> l3
[[1], [1], [1], [1], [1], [1], [1], [1]]
>>>

Describing the above:

l is a *single *list object, containing a single value, 0.

l2 is another single list containing this single list l.

l3 is a third list, constructed to by contatenating the* contents* of l2 8
times. This means l3 effectively ends up containing list l (which is the
contents of l2) 8 times in successtion.  *The contents of list l2 is a
reference to list l.*  So consequently in other words each entry in l3 is
actually a back reference to the ***same original list l***.  That is the
key bit to understand, in order to understand why you're seeing what you're
seeing in your example.

Now to illustrate this, we change the original single list l's first element
to something else, namely 1.  And, as expected, when we then view the
apparent contents of l3, as before, it reflects the contents of list l 8
times, because again, every entry in l3 is actually a reference to the same
original list l, which now contains 1 instead of 0.

So, depending on what you're tring to do, you probably want to change your
data structure in your example in some way to ensure you have new seperate
sublists for each entry in your outer list.

Regards

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


[Tutor] List methods inside a dictionary of list

2011-07-11 Thread Rafael Turner
Hello,

I am playing lists and dictionaries and I came across this
counter-intuitive result.

>>> d = dict(zip(['a', 'q', 'c', 'b', 'e', 'd', 'g', 'j'],8*[[0]]))
>>>d
Out:
{'a': [0],
 'b': [0],
 'c': [0],
 'd': [0],
 'e': [0],
 'g': [0],
 'j': [0],
 'q': [0]}

>>> d['a'].__setitem__(0,4)
>>> d
Out:
{'a': [4],
 'b': [4],
 'c': [4],
 'd': [4],
 'e': [4],
 'g': [4],
 'j': [4],
 'q': [4]}

I was not expecting all the keys to be updated. Is there any
documentation I could read on how different datatypes' methods and
operators interact differently when inside a dictionary?  I would also
like to find a way of being able to use list methods in side a
dictionary so that

>>> d['a'][0] = 5

Does not return

{'a': [5],
 'b': [5],
 'c': [5],
 'd': [5],
 'e': [5],
 'g': [5],
 'j': [5],
 'q': [5]}

But rather

{'a': [5],
 'b': [0],
 'c': [0],
 'd': [0],
 'e': [0],
 'g': [0],
 'j': [0],
 'q': [0]}

Where d is made by d = dict(zip(['a', 'q', 'c', 'b', 'e', 'd', 'g',
'j'],8*[[0]]))

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


Re: [Tutor] list.__init__ within class definition

2011-04-21 Thread Alan Gauld
"Alex Companioni"  wrote 


class Tomato(list):
   def __init__(self, data):
   list.__init__(self, data)

The list.__init__ method (if it is a method, I'm not clear on what
__init__ actually *is*) creates a list, right? 


Not quite.  __init__ (which is a method) is an initialiser not 
a constructor(*). The list is already created when you call 
init(). (Thats done by the __new__() class method)



l = Tomato([1,2,3])

will create a list l with the values [1,2,3], correct?


Correct. But the creation of the list is done in the 
superclass __new__() not in the init. The assignment of 
the data to the list is done by __init__()



(*)Although init is not really a construxctir it is usually treated 
as one and often referred to as such by Python programmers. 
Indeed I do the same in my tutorial. But technically new() 
constructs the class, init initialises it.
 
This is similar to Objective C which also has separate 
constructor/initialiser functions namely alloc and init. So you 
can create an ObjC object like


myObj = [ [MyClass alloc] init ]

But this is such a common combination that ObjC provides 
the wrapper new:


myObj = [MyClass new]

Which is how ObjC programmer create classes 99% of the time!


HTH

--
Alan Gauld
Author of the Learn to Program web site
http://www.alan-g.me.uk/


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


Re: [Tutor] list.__init__ within class definition

2011-04-21 Thread Alan Gauld


"James Mills"  wrote


What you actually want is this:


class Tomato(list):

... def __init__(self, data):
... super(Tomato, self).__init__(data)
...

l = Tomato([1, 2, 3])
l

[1, 2, 3]



Your example:


class Tomato(list):

... def __init__(self, data):
... list.__init__(data)
...

l = Tomato([1, 2, 3])
l

[]




Do you see why ?


This confuses things (at least for me!) It has nothing to 
do with the use of super() but all to do with the use of self.


The OPs style works fuine with self:


class Tomato(list):

...  def __init__(self,data):
...list.__init__(self,data)
...   

t = Tomato([1,2,3])
t

[1, 2, 3]




Using super may be the prefered way of calling the 
superclass but its not the reason the OP code didn't 
work.



--
Alan Gauld
Author of the Learn to Program web site
http://www.alan-g.me.uk/


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


Re: [Tutor] list.__init__ within class definition

2011-04-20 Thread James Mills
On Thu, Apr 21, 2011 at 1:21 PM, Alex Companioni  wrote:
> In the following class definition:
>
> class Tomato(list):
>    def __init__(self, data):
>        list.__init__(self, data)
>
> The list.__init__ method (if it is a method, I'm not clear on what
> __init__ actually *is*) creates a list, right? In other words,
>
> l = Tomato([1,2,3])
>
> will create a list l with the values [1,2,3], correct?

What you actually want is this:

>>> class Tomato(list):
... def __init__(self, data):
... super(Tomato, self).__init__(data)
...
>>> l = Tomato([1, 2, 3])
>>> l
[1, 2, 3]
>>>

Your example:

>>> class Tomato(list):
... def __init__(self, data):
... list.__init__(data)
...
>>> l = Tomato([1, 2, 3])
>>> l
[]
>>>

Do you see why ?

cheers
James

-- 
-- James Mills
--
-- "Problems are solved by method"
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


[Tutor] list.__init__ within class definition

2011-04-20 Thread Alex Companioni
Hey there,

In the following class definition:

class Tomato(list):
def __init__(self, data):
list.__init__(self, data)

The list.__init__ method (if it is a method, I'm not clear on what
__init__ actually *is*) creates a list, right? In other words, 

l = Tomato([1,2,3])

will create a list l with the values [1,2,3], correct?

Thanks,
Alex


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


Re: [Tutor] List sorting issues

2011-03-28 Thread Steven D'Aprano

Eric Stevens wrote:

I am currently designing an address book program, and am trying to design a
method for organizing the keys (which are the names of the entries) for
displaying purposes. I have created a list by doing sortedKeys =
self.addbook.keys() {the self.addbook refers to a dictionary in a custom
class}, and then i try to do a sortedKeys.sort() but never get an
alphabetical list of the keys. All i get is 'None'. I know that a
'list.sort()' returns a None value but all of the tutorials I see show this
giving an alphabetized list.


If you see any tutorial showing list.sort() *returning* a sorted list, 
the tutorial is wrong. But more likely you have misunderstood what you 
are seeing.


list.sort() is an in-place list. So you have to do this:

mylist = ["Fred", "Wilma", "Barney", "Betty"]
mylist.sort()  # Returns None, which we don't bother to keep.
print(mylist)


Or you can use the sorted() function, which returns a new list, leaving 
the original alone:


mylist = ["Fred", "Wilma", "Barney", "Betty"]
print(sorted(mylist))
print(mylist)



 I have also tried doing a 'sorted(self.addbook)' which gives me a list but
not alphabetized. The dictionary keys I am using are 'Eric', 'Kyle', and
'dfd' and they always appear in that order when i use the sorted() feature
(obviously not alphabetized).


Sorting is case sensitive, so "Z" comes before "a". For case insensitive 
sorting, pass a key function to either sorted() or list.sort():


sorted(mylist, key=string.lower)  # Can also use string.upper

Technically, this is not really case-insensitive according to the (very 
complex!) rules for sorting international text, but if your data is all 
English (or at least mostly English) you won't notice the difference.




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


Re: [Tutor] List sorting issues

2011-03-28 Thread Luke Paireepinart
Sort returns none because it changes your list in-place. Print your list out 
after calling sort and you should see the new one.

-
Sent from a mobile device. Apologies for brevity and top-posting.
-

On Mar 28, 2011, at 11:53 AM, Eric Stevens  wrote:

> I am currently designing an address book program, and am trying to design a 
> method for organizing the keys (which are the names of the entries) for 
> displaying purposes. I have created a list by doing sortedKeys = 
> self.addbook.keys() {the self.addbook refers to a dictionary in a custom 
> class}, and then i try to do a sortedKeys.sort() but never get an 
> alphabetical list of the keys. All i get is 'None'. I know that a 
> 'list.sort()' returns a None value but all of the tutorials I see show this 
> giving an alphabetized list.
> 
>  I have also tried doing a 'sorted(self.addbook)' which gives me a list but 
> not alphabetized. The dictionary keys I am using are 'Eric', 'Kyle', and 
> 'dfd' and they always appear in that order when i use the sorted() feature 
> (obviously not alphabetized).
> 
>  Could you please let me know what I am doing wrong or let me know of another 
> way to alphabetize an iterable object. Thank you.
> ___
> Tutor maillist  -  Tutor@python.org
> To unsubscribe or change subscription options:
> http://mail.python.org/mailman/listinfo/tutor
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


[Tutor] List sorting issues

2011-03-28 Thread Eric Stevens
I am currently designing an address book program, and am trying to design a
method for organizing the keys (which are the names of the entries) for
displaying purposes. I have created a list by doing sortedKeys =
self.addbook.keys() {the self.addbook refers to a dictionary in a custom
class}, and then i try to do a sortedKeys.sort() but never get an
alphabetical list of the keys. All i get is 'None'. I know that a
'list.sort()' returns a None value but all of the tutorials I see show this
giving an alphabetized list.

 I have also tried doing a 'sorted(self.addbook)' which gives me a list but
not alphabetized. The dictionary keys I am using are 'Eric', 'Kyle', and
'dfd' and they always appear in that order when i use the sorted() feature
(obviously not alphabetized).

 Could you please let me know what I am doing wrong or let me know of
another way to alphabetize an iterable object. Thank you.
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] list of dictionary

2011-02-25 Thread Pacific Morrowind



On 25/02/2011 9:44 AM, Patty wrote:


- Original Message -
*From:* Pacific Morrowind <mailto:pacificmorrow...@gmail.com>
*To:* tutor@python.org <mailto:tutor@python.org>
*Sent:* Thursday, February 24, 2011 10:21 PM
*Subject:* Re: [Tutor] list of dictionary

Presuming you do have to use the dictionaries:
qty = 0.0
for item in d:

Right here - is the variable 'item' created right on the spot to
iterate over this list?  And I think you are doing the same thing
when you create the variable 'subitem' in the line below, right? 
I am  trying to get myself to recognize an iterator variable as

opposed to a counter variable I create myself  to keep track of
these things (used in other programming languages) - and realizing
the difference between counter/iterator variables and variables
that I really care about like
 'd = []' .
Thanks!
Patty

yes and yes. both item and subitem are created on the spot; anychunk of 
python code like:

for x in y:
will create x as a variable and with each iteration x refers to the next 
item in y;
Of course if I knew the function of the list/dictionary I'd name them 
something more informative than item and subitem - like f.e. for lap in 
d and for time in d if it was refering to races.

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


Re: [Tutor] list of dictionary

2011-02-25 Thread Patty

  - Original Message - 
  From: Pacific Morrowind 
  To: tutor@python.org 
  Sent: Thursday, February 24, 2011 10:21 PM
  Subject: Re: [Tutor] list of dictionary


  Hi;

  On 24/02/2011 9:35 PM, sunil tech wrote: 
Hi all...

i have d=[{'qty':0.0},{'qty':0.0}



  If there isn't some pressing reason to dictionaries as the list items (but 
since I'm not sure how you're generating the list/what you are later using the 
list I can't tell ofc but 

  Hi - I had just a couple comments plus clarification about lists and 
iterating:  

  if applicable to your situation I'd suggest just doing for creation of the 
list
   d = []

  I like creating the empty variable structure, makes the code really clear. 

  (logic for whatever gives your values)
  d.append(value)
  etc.)

when all the qty is 0.0,
i want to perform some print operation
(only at once, after it checks everything in the list of dictionary 'd')...

if its not 0.0,
print some message...

Thank you in advance

  Presuming you do have to use the dictionaries:
  qty = 0.0
  for item in d:

  Right here - is the variable 'item' created right on the spot to iterate over 
this list?  And I think you are doing the same thing when you create the 
variable 'subitem' in the line below, right?  I am  trying to get myself to 
recognize an iterator variable as opposed to a counter variable I create myself 
 to keep track of these things (used in other programming languages) - and 
realizing the difference between counter/iterator variables and variables that 
I really care about like 
   'd = []' .

  Thanks!

  Patty


  for subitem in d:
  if item[subitem] != 0.0:
  qty = item[subitem]
  break
  if qty != 0.0:
  print "some message - for example a non zero qty = %f" % qty

  (presuming you are using Python 2x - if using python 3x the syntax will be 
slightly different)
  Hopefully that will serve your purpose if not just post again and I or one of 
the more frequently posting helpful users here will answer soon.
  Nick




--


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


Re: [Tutor] list of dictionary

2011-02-25 Thread Alan Gauld

"sunil tech"  wrote


i have d=[{'qty':0.0},{'qty':0.0}]

when all the qty is 0.0,
i want to perform some print operation
(only at once, after it checks everything in the list of dictionary 
'd')...


if its not 0.0,
print some message...


Just so I'm clear on the requirement you want something
like:

isZero = True
for each dictionary in d
   if dictionary[qty] is not 0.0
 print some message
 isZero = False
if isZero:
   some print operation

If so that should be easily translated into Python?

HTH,
--
Alan Gauld
Author of the Learn to Program web site
http://www.alan-g.me.uk/


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


Re: [Tutor] list of dictionary

2011-02-24 Thread Pacific Morrowind

Hi;

On 24/02/2011 9:35 PM, sunil tech wrote:

Hi all...

i have d=[{'qty':0.0},{'qty':0.0}]

If there isn't some pressing reason to dictionaries as the list items 
(but since I'm not sure how you're generating the list/what you are 
later using the list I can't tell ofc but if applicable to your 
situation I'd suggest just doing for creation of the list

 d = []
(logic for whatever gives your values)
d.append(value)
etc.)

when all the qty is 0.0,
i want to perform some print operation
(only at once, after it checks everything in the list of dictionary 
'd')...


if its not 0.0,
print some message...

Thank you in advance

Presuming you do have to use the dictionaries:
qty = 0.0
for item in d:
for subitem in d:
if item[subitem] != 0.0:
qty = item[subitem]
break
if qty != 0.0:
print "some message - for example a non zero qty = %f" % qty

(presuming you are using Python 2x - if using python 3x the syntax will 
be slightly different)
Hopefully that will serve your purpose if not just post again and I or 
one of the more frequently posting helpful users here will answer soon.

Nick

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


[Tutor] list of dictionary

2011-02-24 Thread sunil tech
Hi all...

i have d=[{'qty':0.0},{'qty':0.0}]

when all the qty is 0.0,
i want to perform some print operation
(only at once, after it checks everything in the list of dictionary 'd')...

if its not 0.0,
print some message...

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


Re: [Tutor] list of strings

2011-02-09 Thread Hugo Arts
On Wed, Feb 9, 2011 at 11:56 PM, Shawn Matlock  wrote:
> Hello All,
>
> I’m doing something wrong.
> This prints a list of data source names:
>
>     # List all data sources
>     dataSourceList = AdminConfig.list('DataSource') # .split(ls)
>     if verbose == 'True':
>     print 'DEBUG Data Source List: '
>     print dataSourceList
>

[snip]

>
> I expected this to print each data source name in the list. Instead, it is
> printing each character:
>
>     # Modify the data sources so that the aged timeout is set correctly.
>     for dataSource in dataSourceList:
>     print 'DataSource: %s' % dataSource
>     time.sleep(5)
>
> DataSource: "
> DataSource: F
> DataSource: a
> DataSource: c
> DataSource: e
>
>

First off, please use plain text formatting when sending emails to
this list. I like fancy colors as much as the next guy, but html
emails screw up my replies like there's no tomorrow, making me spend
extra work to format everything correctly.

The problem is that dataSourceList is not, as the name implies, a
list, but a string. Iterating over strings happens on a character
basis. If you re-add the .split() that was commented out, you should
get a list. The split method splits the string at the specified
character. To split the string on newlines you can do split('\n') on
linux or split('\r\n') on windows.

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


[Tutor] list of strings

2011-02-09 Thread Shawn Matlock
Hello All,

I'm doing something wrong.

This prints a list of data source names:

# List all data sources
dataSourceList = AdminConfig.list('DataSource') # .split(ls)
if verbose == 'True':
print 'DEBUG Data Source List: '
print dataSourceList

DEBUG Data Source List:
"Facets Data Source(cells/Staging2Cell|resources.xml#DataSource_1267574027582)"
"Facets Extended 
DataSource(cells/Staging2Cell|resources.xml#DataSource_1267574091663)"
"Facets Reporting 
Database(cells/Staging2Cell|resources.xml#DataSource_1267574150361)"
CorpReports(cells/Staging2Cell|resources.xml#DataSource_1270069048670)
DefaultEJBTimerDataSource(cells/Staging2Cell/applications/cisNotesEar.ear/deployments/cisNotesEar|resources.xml#DataSour
ce_1216665969544)
DefaultEJBTimerDataSource(cells/Staging2Cell/nodes/pyxisNode01/servers/Agent01|resources.xml#DataSource_101)
DefaultEJBTimerDataSource(cells/Staging2Cell/nodes/pyxisNode01/servers/DBIC01|resources.xml#DataSource_101)


I expected this to print each data source name in the list. Instead, it is 
printing each character:

# Modify the data sources so that the aged timeout is set correctly.
for dataSource in dataSourceList:
print 'DataSource: %s' % dataSource
time.sleep(5)

DataSource: "
DataSource: F
DataSource: a
DataSource: c
DataSource: e


Thank you,
--
Shawn Matlock
Lead Application Admin
ODS
(503) 228-6554
http://www.odscompanies.com

This message is intended for the sole use of the individual and entity to whom 
it is addressed, and may contain information that is privileged, confidential 
and exempt from disclosure under applicable law. If you are not the intended 
addressee, nor authorized to receive for the intended addressee, you are hereby 
notified that you may not use, copy, disclose or distribute to anyone the 
message or any information contained in the message. If you have received this 
message in error, please immediately advise the sender by reply email and 
delete the message.

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


Re: [Tutor] Homework and the Tutor list

2011-02-02 Thread Rance Hall
On Wed, Feb 2, 2011 at 10:53 AM, Jerry Hill  wrote:

>
> I don't think that's true at all.  I think people here are happy to
> help, including by posting working, efficient, code.  What we try to
> avoid is having students come here with their assignments and have us
> do their schoolwork for them.  I'm not sure how long you've been
> subscribed to the list, but this happens on a regular basis.

> --
> Jerry

I can't agree with Jerry's comments more, and I have been the
benefactor of both sides of this unwritten rule.

As a student, I came to discussion forums like this one with homework
questions hoping for an easy answer, and didn't get one.  Now that I
am a college professor I'm quite glad I didn't get an easy answer, and
I appreciate even more now the fact that forums like this one know a
homework problem from a real one, and work to teach more than normal
when it is needed.

I haven't been involved with python long, and I had an abrupt start on
this list as my first question question was not written with the
protocol I normally use, I had not taken time off and gotten away from
my frustrations and taken the time to write a clear concise
non-judgmental question.  The rest of this list chastised me, and
still helped me.  I deserved the critical words, and did not deserve
the help.  I got both.

Thanks go to the long time readers and contributors of this list who
have made it something valuable, and I hope that some day soon those
of us who are still learning, will be able to begin to meaningfully
contribute.
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


[Tutor] Homework and the Tutor list

2011-02-02 Thread Jerry Hill
>    I would have to agree with you Ian.  Coming from an art then computer
> animation visual effects background, it's not until recently that it became
> evident to me that in order to push the potential of this medium, I would
> definitely have to learn to code.  I think the stigma of the "homework
> bandwagon" comes from the very nature of coding and it's secretive and
> cryptic undertones, it's something very personal in the sense that, although
> there is usually more than 1 way to solve a problem, there's always "THE
> MOST" and more efficient way IMHO, that some people are just not willing to
> share. And, of course, this most efficient way utilizes less memory and
> resources.  This is why I always feel apprehensive to post so I purchased
> many books on python, and until I've gone through them and feel competent
> enough to post, then I'll post, which to me does no good.  Thank you for
> your insight, it makes me feel a little bet more human and inspires me not
> to give up.

I don't think that's true at all.  I think people here are happy to
help, including by posting working, efficient, code.  What we try to
avoid is having students come here with their assignments and have us
do their schoolwork for them.  I'm not sure how long you've been
subscribed to the list, but this happens on a regular basis.

If you're concerned that people will think you're looking for help
with homework, just tell us up front that it's not a homework problem.
 If it *is* a homework problem, tell us that up front too, and people
will still be happy to help, though less likely to post working code,
and more likely to try and work with you to get you to figure out the
solution on your own.

In all cases, you are most likely to get useful help if you do a
couple of things:
Tell us what you're trying to accomplish and why, as clearly as you can.

Post some code that tries to solve the problem, but doesn't work
right.  Ideally, post code that is self contained (so that other
people can run it too), along with any error messages (including the
full stack trace, if one is generated), and what your desired result
is.

Try to give us the big picture of what you're doing, as well as the
details of the problem you're having.  Sometimes we can point you to
an entirely different approach that will work better.

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


Re: [Tutor] list of tutors for python

2011-01-21 Thread Alan Gauld

"bruce"  wrote

Please don't slam me!! I'm working on a project, looking for a 
pretty

good number of pythonistas. Trying to find resources that I should
look to to find them, and thought I would try here for suggestions.


OK, This list is not a recruiting forum for Python tutors.
It is a mailing list where people(specifically Pythonic newbies)
post questions about Python and get answers.

As such it won't help you find recruits for your project, but it may
answer a lot of the questions for which you want to recruit those
experts... In effect you get the entire membership of the list for
free.

HTH,

--
Alan Gauld
Author of the Learn to Program web site
http://www.alan-g.me.uk/


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


Re: [Tutor] list of tutors for python

2011-01-21 Thread Steven D'Aprano

bruce wrote:

Hi guys.

Please don't slam me!! I'm working on a project, looking for a pretty
good number of pythonistas. Trying to find resources that I should
look to to find them, and thought I would try here for suggestions.


I'm sorry, I don't understand what your question is.

If you're looking for Python resources where people can go and get 
advice, this mailing list is one.


The "official" mailing lists run by python.org can be found here:

http://www.python.org/community/lists/
http://mail.python.org/mailman/listinfo

It includes this mailing list, as well as python-l...@python.org which 
is also available on Usenet as comp.lang.python.


You can also look at Reddit and StackOverflow:

http://reddit.com/r/python/
http://stackoverflow.com/questions/tagged/python

There are probably many other places on the internet -- google is your 
friend.


If you are looking for a list of *people*, there is no such list.




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


Re: [Tutor] list of tutors for python

2011-01-21 Thread Emile van Sebille

On 1/21/2011 12:57 PM bruce said...

Hi guys.

Please don't slam me!! I'm working on a project, looking for a pretty
good number of pythonistas. Trying to find resources that I should
look to to find them, and thought I would try here for suggestions.

Any comments would be appreciated.



You're looking for what exactly?

Emile



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


[Tutor] list of tutors for python

2011-01-21 Thread bruce
Hi guys.

Please don't slam me!! I'm working on a project, looking for a pretty
good number of pythonistas. Trying to find resources that I should
look to to find them, and thought I would try here for suggestions.

Any comments would be appreciated.

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


Re: [Tutor] List Changing Order

2010-11-26 Thread Corey Richardson

Steven D'Aprano wrote:

Corey Richardson wrote:

Tutors,

I recall that the keys of dictionaries have arbitrary order, and may 
change over time. Is this true of lists? I can't find the answer from 
a simple Google search. Thank you!


Only if you re-arrange it yourself.

list.sort(), list.reverse() and random.shuffle(list) explicitly change 
the list's order. You can also manually move items around, e.g.:


list[3], list[5] = list[5], list[3]  # swap items 3 and 5

but otherwise lists keep their order.



Many thanks, everyone who replied.
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


[Tutor] [tutor] list order change

2010-11-26 Thread Michael Sprayberry
You can also sort a list so that is ordered in reverse or alphabetically
 
 
Cheers,
Michael


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


Re: [Tutor] List Changing Order

2010-11-25 Thread Steven D'Aprano

Corey Richardson wrote:

Tutors,

I recall that the keys of dictionaries have arbitrary order, and may 
change over time. Is this true of lists? I can't find the answer from a 
simple Google search. Thank you!


Only if you re-arrange it yourself.

list.sort(), list.reverse() and random.shuffle(list) explicitly change 
the list's order. You can also manually move items around, e.g.:


list[3], list[5] = list[5], list[3]  # swap items 3 and 5

but otherwise lists keep their order.


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


Re: [Tutor] List Changing Order

2010-11-25 Thread James Mills
On Fri, Nov 26, 2010 at 1:47 PM, Corey Richardson  wrote:
> I recall that the keys of dictionaries have arbitrary order, and may change
> over time. Is this true of lists? I can't find the answer from a simple
> Google search. Thank you!

items append to a list retain their order.

cheers
James

-- 
-- James Mills
--
-- "Problems are solved by method"
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


[Tutor] List Changing Order

2010-11-25 Thread Corey Richardson

Tutors,

I recall that the keys of dictionaries have arbitrary order, and may 
change over time. Is this true of lists? I can't find the answer from a 
simple Google search. Thank you!

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


Re: [Tutor] List help

2010-11-20 Thread Emile van Sebille

On 11/20/2010 11:06 AM george wu said...

x=0
y=0
w=raw_input("Input: ")
w=list(w)
for x in range(len(w)):
   a=w[x]
   t=0
   print a
   if a==2 or a==4 or a==6 or a==8 or a==10:
 t=a/2
 print "hi"

When I run this program, it doesn't print "hi". Can you please tell me why?



When you're comparing a to 2,4,6,8,10  a is a string representing the 
nth position of the input value w as iterated over with x.


Specifically, a=w[x] which is the list of the input value.

>>> list("hello")
['h', 'e', 'l', 'l', 'o']
>>> list("1234")
['1', '2', '3', '4']


You then compare a string to the numbers 2,4,6,8,10

making the test line:

if a=="2" or a=="4 or a=="6" or a=="8":

should make it print hi.  Note I dropped the 10 as a single charter 
string would never match.


All this is likely beside the point -- what were you trying to have happen?

Emile


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


[Tutor] List help

2010-11-20 Thread george wu
x=0
y=0
w=raw_input("Input: ")
w=list(w)
for x in range(len(w)):
  a=w[x]
  t=0
  print a
  if a==2 or a==4 or a==6 or a==8 or a==10:
t=a/2
print "hi"

When I run this program, it doesn't print "hi". Can you please tell me why?



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


Re: [Tutor] List comprehension question

2010-11-13 Thread Steven D'Aprano

Richard D. Moores wrote:

On Fri, Nov 12, 2010 at 15:26, Steven D'Aprano  wrote:



   best = t.repeat(number=1, repeat=5)
   print round(best, 3)


t.repeat(number=1, repeat=5) is a list of the 5 times, not the
best of the 5.


Oops! Good catch. Sorry about that.



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


Re: [Tutor] List comprehension question

2010-11-12 Thread Richard D. Moores
On Fri, Nov 12, 2010 at 23:25, Richard D. Moores  wrote:

> See 

Sorry, forgot to paste.


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


Re: [Tutor] List comprehension question

2010-11-12 Thread Richard D. Moores
On Fri, Nov 12, 2010 at 15:26, Steven D'Aprano  wrote:
> Richard D. Moores wrote:
>
>> OK, but why can't I do what the timeit doc suggests, only put 2 or
>> more functions in the file, as I do here:
>> 
>>
>> def test():
>>    "Stupid test function"
>>    L = []
>>    for i in range(100):
>>        L.append(i)
>>
>> if __name__=='__main__':
>>    from timeit import Timer
>>    t = Timer("test()", "from __main__ import test")
>>    print t.timeit()
>
>
> There's nothing wrong with that, except that running the test *once* (as you
> do) is subject to greater chance fluctuations than running it multiple
> times: change the last line to:
>
> print min(t.repeat())
>
> Note that you don't *have* to do this, the world will not end if you don't,
> but your timing results will be just a little more accurate if you do.
>
> If you want to time multiple functions, just use multiple timer objects:
>
> t1 = Timer("test()", "from __main__ import test")
> t2 = Timer("spam()", "from module import spam")
> t3 = Timer("ham()", "from module import ham")
>
>
>> I'm sorry, Steven, but could you revise this code to use repeat=5
>> instead of the for loop? I can't see how to do it.
>
> You don't need to choose repeat=5. The default is 3, but you can specify any
> number you like. I just like 5 :)

So I'll go with your 5.

>> if __name__=='__main__':
>>    from timeit import Timer
>>    for y in range(5):
>>        t = Timer("proper_divisors_sum1(50)", "from __main__
>> import proper_divisors_sum")
>>        print round(t.timeit(number=1),3)
>
> if __name__=='__main__':
>    from timeit import Timer
>    t = Timer("proper_divisors_sum(50)",
>        "from __main__ import proper_divisors_sum")
>    best = t.repeat(number=1, repeat=5)
>    print round(best, 3)

t.repeat(number=1, repeat=5) is a list of the 5 times, not the
best of the 5. So I used
min(t.repeat(number=1, repeat=5))

See 

Thanks very much, Steven!
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] List comprehension question

2010-11-12 Thread Steven D'Aprano

Richard D. Moores wrote:


OK, but why can't I do what the timeit doc suggests, only put 2 or
more functions in the file, as I do here:


def test():
"Stupid test function"
L = []
for i in range(100):
L.append(i)

if __name__=='__main__':
from timeit import Timer
t = Timer("test()", "from __main__ import test")
print t.timeit()



There's nothing wrong with that, except that running the test *once* (as 
you do) is subject to greater chance fluctuations than running it 
multiple times: change the last line to:


print min(t.repeat())

Note that you don't *have* to do this, the world will not end if you 
don't, but your timing results will be just a little more accurate if 
you do.


If you want to time multiple functions, just use multiple timer objects:

t1 = Timer("test()", "from __main__ import test")
t2 = Timer("spam()", "from module import spam")
t3 = Timer("ham()", "from module import ham")



I'm sorry, Steven, but I could you revise this code to use repeat=5
instead of the for loop? I can't see how to do it.


You don't need to choose repeat=5. The default is 3, but you can specify 
any number you like. I just like 5 :)




if __name__=='__main__':
from timeit import Timer
for y in range(5):
t = Timer("proper_divisors_sum1(50)", "from __main__
import proper_divisors_sum")
print round(t.timeit(number=1),3)


if __name__=='__main__':
from timeit import Timer
t = Timer("proper_divisors_sum(50)",
"from __main__ import proper_divisors_sum")
best = t.repeat(number=1, repeat=5)
print round(best, 3)




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


Re: [Tutor] List comprehension question

2010-11-12 Thread Richard D. Moores
On Fri, Nov 12, 2010 at 07:13, David Hutto  wrote:

> import timeit
>
>
> def anyName():
>        pass
>
> t = timeit.Timer('anyName()','from __main__ import anyName')
> print t.repeat(repeat=5)
>
>
> If I get the gist of what you're asking.
>

Yes. That's it! Thank you! And if I don't want the default number of 1
million, I can use
print t.repeat(repeat=5,number=3000)

See  where I compare speeds of
2 functions.

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


Re: [Tutor] List comprehension question

2010-11-12 Thread David Hutto
Apologies, missed that part. Didn't mean to seem rude.

import timeit


def anyName():
pass

for num in range(10):
t = timeit.Timer('anyName()','from __main__ import anyName')
print t.repeat(repeat=5)

#or

import timeit


def anyName():
pass

t = timeit.Timer('anyName()','from __main__ import anyName')
print t.repeat(repeat=5)


If I get the gist of what you're asking.
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] List comprehension question

2010-11-12 Thread Richard D. Moores
On Fri, Nov 12, 2010 at 05:15, David Hutto  wrote:
>>        repeatedly, returning a list of results. ...
>>
>> I'm sorry, Steven, but I could you revise this code to use repeat=5
>> instead of the for loop? I can't see how to do it.
>
 help(timeit.Timer
>
>  repeat(self, repeat=3, number=100)
>  |      Call timeit() a few times.
>  |
>  |      This is a convenience function that calls the timeit()
>  |      repeatedly, returning a list of results.  The first argument
>  |      specifies how many times to call timeit(), defaulting to 3;
>  |      the second argument specifies the timer argument, defaulting
>  |      to one million.
>  |
>  |      Note: it's tempting to calculate mean and standard deviation
>  |      from the result vector and report these.  However, this is not
>  |      very useful.  In a typical case, the lowest value gives a
>  |      lower bound for how fast your machine can run the given code
>  |      snippet; higher values in the result vector are typically not
>  |      caused by variability in Python's speed, but by other
>  |      processes interfering with your timing accuracy.  So the min()
>  |      of the result is probably the only number you should be
>  |      interested in.  After that, you should look at the entire
>  |      vector and apply common sense rather than statistics.

Look, I've already shown I know where the docs are, and have read
them. I don't understand how to use repeat() with my code. Wasn't that
clear to you?
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] List comprehension question

2010-11-12 Thread David Hutto
>        repeatedly, returning a list of results. ...
>
> I'm sorry, Steven, but I could you revise this code to use repeat=5
> instead of the for loop? I can't see how to do it.

>>> help(timeit.Timer

 repeat(self, repeat=3, number=100)
 |  Call timeit() a few times.
 |
 |  This is a convenience function that calls the timeit()
 |  repeatedly, returning a list of results.  The first argument
 |  specifies how many times to call timeit(), defaulting to 3;
 |  the second argument specifies the timer argument, defaulting
 |  to one million.
 |
 |  Note: it's tempting to calculate mean and standard deviation
 |  from the result vector and report these.  However, this is not
 |  very useful.  In a typical case, the lowest value gives a
 |  lower bound for how fast your machine can run the given code
 |  snippet; higher values in the result vector are typically not
 |  caused by variability in Python's speed, but by other
 |  processes interfering with your timing accuracy.  So the min()
 |  of the result is probably the only number you should be
 |  interested in.  After that, you should look at the entire
 |  vector and apply common sense rather than statistics.





>
> if __name__=='__main__':
>    from timeit import Timer
>    for y in range(5):
>        t = Timer("proper_divisors_sum1(50)", "from __main__
> import proper_divisors_sum")
>        print round(t.timeit(number=1),3)
>
> Thanks,
>
> Dick
> ___
> Tutor maillist  -  tu...@python.org
> To unsubscribe or change subscription options:
> http://mail.python.org/mailman/listinfo/tutor
>
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] List comprehension question

2010-11-12 Thread Richard D. Moores
On Fri, Nov 12, 2010 at 02:11, Steven D'Aprano  wrote:
> Richard D. Moores wrote:
>
>> I find using that at the interactive prompt a bit onerous -- lots of
>> copy and pasting. And doubly so when comparing times for 2 or more
>> functions.
>
> Does your Python not support readline? Normally, if you press UP ARROW or
> DOWN ARROW, Python will cycle through the previous interpreter lines.

Do you mean my IDE? IDLE does that with Alt+P and Alt+N. I'm dealing
with multi-line functions, not single lines. If I paste a function at
the prompt, IDLE will bring the whole thing back with Alt+P. Problem
is, IDLE isn't my IDE -- Wing is.

> Another approach is to write helper functions, or use string interpolation,
> to make it easy to re-use code:
>
> setup = "from __main__ import %s as func"
> test = "func(1000)"
> t1 = Timer(test, setup % "my_func")
> t1 = Timer(test, setup % "your_func")
>
> A third approach might be to treat your testing as a script. Put all your
> test code in a module, and then run it:
>
> python time_test.py

OK, but why can't I do what the timeit doc suggests, only put 2 or
more functions in the file, as I do here:


def test():
"Stupid test function"
L = []
for i in range(100):
L.append(i)

if __name__=='__main__':
from timeit import Timer
t = Timer("test()", "from __main__ import test")
print t.timeit()

>> The timeit doc gave me the obvious idea of how to avoid the prompt and
>> also easily compare the times of 2 or more functions. I'd like to know
>> if doing it this way is correct: Please see
>> 
>
> You're vulnerable to statistical outliers (which are remarkably common on
> multi-tasking operating systems!) cause by the OS calling some other program
> in the middle of yours. Call each time test three or five times, and use the
> smallest.

Sure, I do that with the for loops, don't I?

>> Huh. Just realized that this timing method doesn't include the 5
>> repeats called for by Steven's method. So how about using a for loop?
>> As in .
>
> You're still re-inventing the wheel. timeit already includes a method for
> doing exactly that: repeat. From the documentation:
>
>    def repeat(self, repeat=default_repeat, number=default_number):
>        """Call timeit() a few times.
>
>        This is a convenience function that calls the timeit()
>        repeatedly, returning a list of results. ...

I'm sorry, Steven, but I could you revise this code to use repeat=5
instead of the for loop? I can't see how to do it.

if __name__=='__main__':
from timeit import Timer
for y in range(5):
t = Timer("proper_divisors_sum1(50)", "from __main__
import proper_divisors_sum")
print round(t.timeit(number=1),3)

Thanks,

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


Re: [Tutor] List comprehension question

2010-11-12 Thread Steven D'Aprano

Richard D. Moores wrote:


I find using that at the interactive prompt a bit onerous -- lots of
copy and pasting. And doubly so when comparing times for 2 or more
functions.


Does your Python not support readline? Normally, if you press UP ARROW 
or DOWN ARROW, Python will cycle through the previous interpreter lines.


Another approach is to write helper functions, or use string 
interpolation, to make it easy to re-use code:


setup = "from __main__ import %s as func"
test = "func(1000)"
t1 = Timer(test, setup % "my_func")
t1 = Timer(test, setup % "your_func")

A third approach might be to treat your testing as a script. Put all 
your test code in a module, and then run it:


python time_test.py



The timeit doc gave me the obvious idea of how to avoid the prompt and
also easily compare the times of 2 or more functions. I'd like to know
if doing it this way is correct: Please see



You're vulnerable to statistical outliers (which are remarkably common 
on multi-tasking operating systems!) cause by the OS calling some other 
program in the middle of yours. Call each time test three or five times, 
and use the smallest.




Huh. Just realized that this timing method doesn't include the 5
repeats called for by Steven's method. So how about using a for loop?
As in .


You're still re-inventing the wheel. timeit already includes a method 
for doing exactly that: repeat. From the documentation:


def repeat(self, repeat=default_repeat, number=default_number):
"""Call timeit() a few times.

This is a convenience function that calls the timeit()
repeatedly, returning a list of results. ...



97% of the time you think you want to call timeit, you actually should 
be calling min(timer.repeat()) instead.




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


Re: [Tutor] List comprehension question

2010-11-11 Thread Stefan Behnel

Steven D'Aprano, 12.11.2010 06:07:

Richard D. Moores wrote:

On Wed, Nov 10, 2010 at 01:30, Steven D'Aprano wrote:



P.S. don't take that as a put down -- you should be pleased that your
code is around as fast as Tim Peter's code :)


Nah. But where is Tim Peter's code?


The timeit module was written by Tim Peters. Since then, others have
contributed as well, but the basic recipe is his.


The OP might have been referring to the stackoverflow comment that quotes 
the algorithm solving the OP's problem:


http://stackoverflow.com/questions/1024640/calculating-phik-for-1kn



For those who don't know, Tim Peters, a.k.a. the timbot, is one of the
old-time Python demigods. He is responsible for not one, but two,
awesomely fast sort routines: the original list.sort() method was his,
and then around Python 2.3 (I think) he re-wrote it using a new sort
method which is even faster, added stability, and has fewer special
cases than the previous version. This sort algorithm has since been
adopted by Android and Java 7.


It's commonly referred to as "Timsort".

http://en.wikipedia.org/wiki/Timsort
http://bugs.python.org/file4451/timsort.txt
http://corte.si/posts/code/timsort/index.html

Stefan

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


Re: [Tutor] List comprehension question

2010-11-11 Thread Steven D'Aprano

Richard D. Moores wrote:

On Wed, Nov 10, 2010 at 01:30, Steven D'Aprano  wrote:



P.S. don't take that as a put down -- you should be pleased that your code is 
around as fast as Tim Peter's code :)


Nah. But where is Tim Peter's code?



The timeit module was written by Tim Peters. Since then, others have 
contributed as well, but the basic recipe is his.


For those who don't know, Tim Peters, a.k.a. the timbot, is one of the 
old-time Python demigods. He is responsible for not one, but two, 
awesomely fast sort routines: the original list.sort() method was his, 
and then around Python 2.3 (I think) he re-wrote it using a new sort 
method which is even faster, added stability, and has fewer special 
cases than the previous version. This sort algorithm has since been 
adopted by Android and Java 7.



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


Re: [Tutor] List comprehension question

2010-11-11 Thread Richard D. Moores
On Wed, Nov 10, 2010 at 02:35, Steven D'Aprano  wrote:
> Richard D. Moores wrote:
>>
>> On Tue, Nov 9, 2010 at 12:54, Steven D'Aprano  wrote:
>>>
>>> Richard D. Moores wrote:
>>>
 See  for a speed test with n =
 100,000 and 100,000 loops
>>>
>>> As a general rule, you shouldn't try to roll your own speed tests. There
>>> are
>>> various subtleties that can throw your results right out. Timing small
>>> code
>>> snippets on modern multi-tasking computers is fraught with difficulties.
>>
>> Yes, but I thought that if I ran the tests the way I did, several
>> times and then reversing the order of the functions, and seeing that
>> the results were very similar, I could be pretty sure of my findings.
>> Could you point out where taking even that amount of care could lead
>> me astray?
>
> Well, the biggest problem is that you're re-inventing the wheel. But in
> truth, what you did was not terrible, particularly if you're using Python 3
> where range() is quite lightweight rather than a heavy operation that
> creates a big list.
>
> There are various traps when timing code:
>
> * There are commonly two functions you use for getting the time: time.time()
> and time.clock(). On Windows, the best one to use is clock(), but on other
> operating systems, you should probably use time().  The timeit module
> automatically chooses the right one for you.

Thanks for this! My memory had it reversed: time() best for windows;
clock() for the rest. So I'm now doing a lot of search and replace on
old scripts.

And I reread the timeit doc. I found this down at the bottom of
:

==begin quote from timeit module doc=
To give the timeit module access to functions you define, you can pass
a setup parameter which contains an import statement:

def test():
"Stupid test function"
L = [i for i in range(100)]

if __name__=='__main__':
from timeit import Timer
t = Timer("test()", "from __main__ import test")
print(t.timeit())
end quote from timeit module doc==

Earlier in this thread you gave us/me this:

begin wisdom from Steven=
At the Python interactive interpreter, the most useful pattern I've found is:

from timeit import Timer
t = Timer("proper_divisors(n)",
   "from __main__ import proper_divisors; n = 10")
min(t.repeat(repeat=5, number=10))


Or if you're happy with Python's defaults, that last line can be just:

min(t.repeat())
===temporary end of wisdom from Steven=

I find using that at the interactive prompt a bit onerous -- lots of
copy and pasting. And doubly so when comparing times for 2 or more
functions.

The timeit doc gave me the obvious idea of how to avoid the prompt and
also easily compare the times of 2 or more functions. I'd like to know
if doing it this way is correct: Please see


Huh. Just realized that this timing method doesn't include the 5
repeats called for by Steven's method. So how about using a for loop?
As in .

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


Re: [Tutor] List comprehension question

2010-11-11 Thread Richard D. Moores
On Wed, Nov 10, 2010 at 01:30, Steven D'Aprano  wrote:
>
> Richard D. Moores wrote:
>
>> def proper_divisors_sum(n):
>>    return sum(list(divisors(n))) - n
>
> There's no need to call list first. sum() will happily operate on any sort of 
> iterable -- lists, sums, iterators, generators, range objects. Anything 
> except strings, which would be pointless even if you could do it, which you 
> can't, but even so you can fool sum() to work with strings with a bit of 
> effort.
>
>
>> Using Steven's suggested speed test
>> this gets 6.2404818210135886
>>
>> My up-to-now fastest version,
>
> [...]
>>
>> gets 6.1753780857622473
>>
>> So they're about even.
>
> I'd say that the difference is probably statistically insignificant. Even if 
> it's consistent on your PC, on another PC with a slightly different 
> processor, slightly different memory, or a different operating system, it 
> could very well go the other way.

I think that's what I meant. :)

> In any case, since those times are ~6 seconds per 100,000 loops, the real 
> difference is only 60 microseconds -- completely trivial unless you're doing 
> some *serious* number crunching.
>
>
> P.S. don't take that as a put down -- you should be pleased that your code is 
> around as fast as Tim Peter's code :)

Nah. But where is Tim Peter's code?

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


Re: [Tutor] List comprehension question

2010-11-10 Thread Steven D'Aprano

Richard D. Moores wrote:

On Tue, Nov 9, 2010 at 12:54, Steven D'Aprano  wrote:

Richard D. Moores wrote:


See  for a speed test with n =
100,000 and 100,000 loops

As a general rule, you shouldn't try to roll your own speed tests. There are
various subtleties that can throw your results right out. Timing small code
snippets on modern multi-tasking computers is fraught with difficulties.


Yes, but I thought that if I ran the tests the way I did, several
times and then reversing the order of the functions, and seeing that
the results were very similar, I could be pretty sure of my findings.
Could you point out where taking even that amount of care could lead
me astray?


Well, the biggest problem is that you're re-inventing the wheel. But in 
truth, what you did was not terrible, particularly if you're using 
Python 3 where range() is quite lightweight rather than a heavy 
operation that creates a big list.


There are various traps when timing code:

* There are commonly two functions you use for getting the time: 
time.time() and time.clock(). On Windows, the best one to use is 
clock(), but on other operating systems, you should probably use time(). 
 The timeit module automatically chooses the right one for you.


* Comparing apples and oranges. There's not a lot that timeit can do 
there, since it requires you *understand* what the code is that you are 
timing, but it helps by allowing you to split initialisation away from 
the code you are timing.


* Timing too much. One trap is to do this:

t = time.time()
for _ in range(100):
do_something()
t = time.time() - t

This is especially bad in Python 2.x!

The problem is that you are including the time it takes to create a list 
of one million integers in your timing code. That's like starting the 
stop watch at a race while the athletes are still in the changing rooms, 
getting dressed, and yet you'd be amazed how often people do it! If the 
time taken by each call to do_something() is very large, then the extra 
time will be negligible, but if do_something is a fast snippet, it might 
take you nearly as long to build the list as it does to run the code 
you're trying to time!


timeit ensures that as little as possible overhead is included in the 
execution being timed.


* Forgetting that computers are multi-tasking machines these days. At 
every instant, the operating system is giving tiny time-slices to your 
program and potentially dozens of others. If you're busy loading a dozen 
web pages, playing a DVD, compiling a large program and trying to time a 
code snippet, it will be obvious that everything is going to be running 
slow. But if you time something *once*, what's not obvious is that just 
by chance you might get a number that is much slower than normal because 
the OS *just happened* to call your anti-virus during the test. timeit 
fights against that by running your code in a loop, and then working out 
the average time per loop, *and* then repeating the loop multiple times 
(three by default) and picking the lowest figure. Higher figures are 
slower due to external factors.


* Forgetting your CPU cache effects. Modern CPUs do all sorts of amazing 
wizardry to make code run fast. Sometimes slow, but hopefully more often 
fast. The first time you run a piece of code, chances are it will be 
slower than normal, because the hardware caches will have other stuff in 
them. But the second time, the code and data will already be lined up in 
the cache and pipelines ready to go. This is why if you time something a 
dozen times, the *first* time could be two or three times slower than 
the rest.



I've probably forgotten some... but anyway, the important thing is that 
there's lots of subtleties to timing code, and Tim Peters has already 
thought of them so you don't have to :)




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


Re: [Tutor] List comprehension question

2010-11-10 Thread Steven D'Aprano

Richard D. Moores wrote:


def proper_divisors_sum(n):
return sum(list(divisors(n))) - n


There's no need to call list first. sum() will happily operate on any 
sort of iterable -- lists, sums, iterators, generators, range objects. 
Anything except strings, which would be pointless even if you could do 
it, which you can't, but even so you can fool sum() to work with strings 
with a bit of effort.




Using Steven's suggested speed test
this gets 6.2404818210135886

My up-to-now fastest version,

[...]

gets 6.1753780857622473

So they're about even.


I'd say that the difference is probably statistically insignificant. 
Even if it's consistent on your PC, on another PC with a slightly 
different processor, slightly different memory, or a different operating 
system, it could very well go the other way.


In any case, since those times are ~6 seconds per 100,000 loops, the 
real difference is only 60 microseconds -- completely trivial unless 
you're doing some *serious* number crunching.



P.S. don't take that as a put down -- you should be pleased that your 
code is around as fast as Tim Peter's code :)



--
Steven

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


Re: [Tutor] List comprehension question

2010-11-09 Thread Stefan Behnel

Richard D. Moores, 10.11.2010 08:24:

def proper_divisors_sum(n):
 pd = set((1,))
 for x in range(2, int(n**.5)+1):
 if n % x == 0:
 pd.update((x, n//x))
 return sum(list(pd))


You keep using redundant operations. What "sum(list(s))" does, for s being 
a set, is:


1) create a list of the length of s
2) iterate over s, copying elements into the list
3) sum up the values in the list

What makes you think that the intermediate list is needed?

$ python2.6 -m timeit -s 's = set(range(1000))' 'sum(list(s))'
1 loops, best of 3: 20.7 usec per loop
$ python2.6 -m timeit -s 's = set(range(1000))' 'sum(s)'
10 loops, best of 3: 14.4 usec per loop

Stefan

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


Re: [Tutor] List comprehension question

2010-11-09 Thread Richard D. Moores
On Tue, Nov 9, 2010 at 18:29, C or L Smith  wrote:

> >From sympy you simply do:
>
 from sympy import divisors
 list(divisors(256))
> [1, 2, 4, 8, 16, 32, 64, 128, 256]
>
> So your proper divisors would just be sum(divisors(n)) - n.
> The divisors function there is in the ntheory/factor_.py file.

Thanks for letting me know about this.

def proper_divisors_sum(n):
return sum(list(divisors(n))) - n

Using Steven's suggested speed test
this gets 6.2404818210135886

My up-to-now fastest version,

def proper_divisors_sum(n):
pd = set((1,))
for x in range(2, int(n**.5)+1):
if n % x == 0:
pd.update((x, n//x))
return sum(list(pd))

gets 6.1753780857622473

So they're about even.

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


Re: [Tutor] List comprehension question

2010-11-09 Thread C or L Smith
>>   1. Re: List comprehension question (Richard D. Moores)
>>> ?: def proper_divisors_sum(n):

>>> A few questions--noting, of course, that I'm not reading this with
>>> an eye toward performance, which it seems you are, but these occur
>>> to me:

Tim Peters had a beautiful little version of divisors at

http://stackoverflow.com/questions/1010381/python-factorization

A modified version of this is part of the python CAS system sympy (sympy.org). 
>From sympy you simply do:

>>> from sympy import divisors
>>> list(divisors(256))
[1, 2, 4, 8, 16, 32, 64, 128, 256]

So your proper divisors would just be sum(divisors(n)) - n.
The divisors function there is in the ntheory/factor_.py file.

/c





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


Re: [Tutor] List comprehension question

2010-11-09 Thread Alan Gauld


"Richard D. Moores"  wrote


Question: When I dump in more that one line of any code (properly
indented), after running it once, I've never known how to run it 
again

without a redump. The up arrow just gets me one line at a time. So,
how to do it?


It depends on your IDE.

On IDLE I think its Alt-P and Alt-N to cycle through previous and
next lines of history.

On Pythonwin its Ctrl-Up/Ctrl-Down

IDLE and Pythonwin put in whole blocks.

The XP CMD prompt uses up/down keys but only does single lines

A La Mode had some neat cut n paste features for correctly pasting
in blocks of code evern from other places - like email

Not sure about any of the others.

Alan FG. 



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


Re: [Tutor] List comprehension question

2010-11-09 Thread Richard D. Moores
On Tue, Nov 9, 2010 at 12:54, Steven D'Aprano  wrote:
> Richard D. Moores wrote:
>
>> See  for a speed test with n =
>> 100,000 and 100,000 loops
>
> As a general rule, you shouldn't try to roll your own speed tests. There are
> various subtleties that can throw your results right out. Timing small code
> snippets on modern multi-tasking computers is fraught with difficulties.

Yes, but I thought that if I ran the tests the way I did, several
times and then reversing the order of the functions, and seeing that
the results were very similar, I could be pretty sure of my findings.
Could you point out where taking even that amount of care could lead
me astray?

>
> Fortunately Python comes with that battery already included: the timeit
> module. You can use it from the shell like this:
>
> python -m timeit -s "setup code goes here" "test code goes here"
>
> At the Python interactive interpreter, the most useful pattern I've found
> is:
>
> from timeit import Timer
> t = Timer("proper_divisors(n)",
>    "from __main__ import proper_divisors; n = 10")
> min(t.repeat(repeat=5, number=10))
>
>
> Or if you're happy with Python's defaults, that last line can be just:
>
> min(t.repeat())

That's terrific, Stephen! I've used timeit before, but only for really
small snippets. With your encouragement I experimented and after some
trial and error, I came up with this method for using your template:

1. Don't try to dump all you (Steven) wrote in at once.
2. First, do the import.
>>> from timeit import Timer
3. Then dump in the function (steps 2 and 3 can be reversed, I think)
4. then
 >>>t = Timer("proper_divisors(n)",
  "from __main__ import proper_divisors; n = 10")
5. Finally,
>>>min(t.repeat(repeat=5, number=10))
6. Wait for the result.

(please tell me if I could cut down the number of steps by combining a
couple of them.)

I was pleased that for

def proper_divisors(n):
pd = set((1,))
for x in range(2, int(n**.5)+1):
if n % x == 0:
pd.update((x, n//x))
return sum(list(pd))

I got 8.312734300029753

and for

def proper_divisors(n):
pd = set((1,))
for x in range(2, int(n**.5)+1):
factor, mod = divmod(n,x)
if mod == 0:
pd.update((x,factor))
return sum(list(pd))

got 14.859849506012608

That's about the same speed ratio (1.79) that I reported here earlier,
I believe. I quote: "It may be that I haven't done your suggestions
justice, but that
function is 76% slower than proper_divisors_sum2()"

Question: When I dump in more that one line of any code (properly
indented), after running it once, I've never known how to run it again
without a redump. The up arrow just gets me one line at a time. So,
how to do it?

Thanks,

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


Re: [Tutor] List comprehension question

2010-11-09 Thread Albert-Jan Roskam
For larger blocks of code, cProfile may also be useful for speed tests.

 Cheers!!
Albert-Jan


~~
All right, but apart from the sanitation, the medicine, education, wine, public 
order, irrigation, roads, a fresh water system, and public health, what have 
the 
Romans ever done for us?
~~





From: Steven D'Aprano 
To: tutor@python.org
Sent: Tue, November 9, 2010 9:54:24 PM
Subject: Re: [Tutor] List comprehension question

Richard D. Moores wrote:

> See <http://tutoree7.pastebin.com/R82876Eg> for a speed test with n =
> 100,000 and 100,000 loops

As a general rule, you shouldn't try to roll your own speed tests. There are 
various subtleties that can throw your results right out. Timing small code 
snippets on modern multi-tasking computers is fraught with difficulties.

Fortunately Python comes with that battery already included: the timeit module. 
You can use it from the shell like this:

python -m timeit -s "setup code goes here" "test code goes here"

At the Python interactive interpreter, the most useful pattern I've found is:

from timeit import Timer
t = Timer("proper_divisors(n)",
"from __main__ import proper_divisors; n = 10")
min(t.repeat(repeat=5, number=10))


Or if you're happy with Python's defaults, that last line can be just:

min(t.repeat())



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



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


Re: [Tutor] List comprehension question

2010-11-09 Thread Steven D'Aprano

Richard D. Moores wrote:


See  for a speed test with n =
100,000 and 100,000 loops


As a general rule, you shouldn't try to roll your own speed tests. There 
are various subtleties that can throw your results right out. Timing 
small code snippets on modern multi-tasking computers is fraught with 
difficulties.


Fortunately Python comes with that battery already included: the timeit 
module. You can use it from the shell like this:


python -m timeit -s "setup code goes here" "test code goes here"

At the Python interactive interpreter, the most useful pattern I've 
found is:


from timeit import Timer
t = Timer("proper_divisors(n)",
"from __main__ import proper_divisors; n = 10")
min(t.repeat(repeat=5, number=10))


Or if you're happy with Python's defaults, that last line can be just:

min(t.repeat())



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


Re: [Tutor] List comprehension question

2010-11-09 Thread Richard D. Moores
On Tue, Nov 9, 2010 at 05:51, Martin A. Brown  wrote:
>
> Hello,
>
>  : def proper_divisors_sum(n):
>  :     pd_list = []
>  :     for x in range(1, int(n**.5)+1):
>  :         if n % x == 0:
>  :             factor = int(x)
>  :             pd_list.append(factor)
>  :             factor2 = int(n/factor)
>  :             pd_list.append(factor2)
>  :     pd_list = list(set(pd_list))
>  :     pd_list.sort()
>  :     pd_list = pd_list[:-1]
>  :     return sum(pd_list)
>
> A few questions--noting, of course, that I'm not reading this with
> an eye toward performance, which it seems you are, but these occur
> to me:
>
>  * Why use a list (pd_list = []), when you want unique divisors?
>    Why not, pd = set() ?  Then, instead of pd_list.append(factor),
>    pd.add(factor) or something like pd.update((factor,factor2))?
>    (See also my suggestion below.)
>
>  * Also, since you are throwing away the divisor n, anyway,
>    why not skip it from the beginning?  Like this:
>
>      pd_list = [1,]
>      for x in range(2, int(n**.5)+1):
>
>  * So, I'm not terribly math aware, but I don't think I have
>    substantially changed the meaning of your program.  I find
>    breaking out the functions makes things a bit clearer to
>    somebody who might be reading my code later.
>
> Combining these suggestions and splitting into separate functions
> (you don't really need to sort before summing), I end up with the
> below.  Note, that I stuff the proper divisor 1 in the set at
> creation time.  This is probably not worth it from an optimization
> perspective, but as I have learned, the only way to know is to time
> it (and I didn't time it).
>
>      def proper_divisors_sum(n):
>          return sum(proper_divisors(n))
>
>      def proper_divisors_sorted(n):
>          return sorted(proper_divisors(n))
>
>      def proper_divisors(n):
>          pd = set((1,))
>          for x in range(2, int(n**.5)+1):
>              factor, mod = divmod(n,x)
>              if mod == 0:
>                  pd.update((x,factor))
>          return list(pd)

Thanks for your ideas, Martin. I adopted your idea of starting at 2,
with an initial list of [1].  It resulted in a small increase in
speed. And you're right, I don't need to sort.

Speed is important, because the function is the heart of my amiable
numbers script. Did you happen to see that post of mine?

#Here's my fastest version before seeing Martin's post:
def proper_divisors_sum1(n):
pd_list = []
for x in range(1, int(n**.5)+1):
if n % x == 0:
pd_list.append(x)
pd_list.append(n//x)
pd_list = list(set(pd_list))
pd_list.sort()
pd_list = pd_list[:-1]
return sum(pd_list)

#This uses several of Martin's ideas
# It's now my fastest version
def proper_divisors_sum2(n):
pd = set((1,))
for x in range(2, int(n**.5)+1):
if n % x == 0:
pd.update((x, n//x))
return sum(list(pd))

Here's what I put together from all your points, except for the
splitting off of several small functions:

# This incorporates all of Martin's ideas
# Seems that divmod() is a speed killer
def proper_divisors_sum3(n):
pd = set((1,))
for x in range(2, int(n**.5)+1):
factor, mod = divmod(n,x)
if mod == 0:
pd.update((x,factor))
return sum(list(pd))

It may be that I've haven't done your suggestions justice, but that
function is 76% slower than proper_divisors_sum2().

See  for a speed test with n =
100,000 and 100,000 loops

Thanks again, Martin.

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


Re: [Tutor] List comprehension question

2010-11-09 Thread Martin A. Brown

Hello,

 : def proper_divisors_sum(n):
 : pd_list = []
 : for x in range(1, int(n**.5)+1):
 : if n % x == 0:
 : factor = int(x)
 : pd_list.append(factor)
 : factor2 = int(n/factor)
 : pd_list.append(factor2)
 : pd_list = list(set(pd_list))
 : pd_list.sort()
 : pd_list = pd_list[:-1]
 : return sum(pd_list)

A few questions--noting, of course, that I'm not reading this with 
an eye toward performance, which it seems you are, but these occur 
to me:

  * Why use a list (pd_list = []), when you want unique divisors?
Why not, pd = set() ?  Then, instead of pd_list.append(factor), 
pd.add(factor) or something like pd.update((factor,factor2))?
(See also my suggestion below.)

  * Also, since you are throwing away the divisor n, anyway, 
why not skip it from the beginning?  Like this:

  pd_list = [1,] 
  for x in range(2, int(n**.5)+1):

  * So, I'm not terribly math aware, but I don't think I have 
substantially changed the meaning of your program.  I find 
breaking out the functions makes things a bit clearer to 
somebody who might be reading my code later.

Combining these suggestions and splitting into separate functions 
(you don't really need to sort before summing), I end up with the 
below.  Note, that I stuff the proper divisor 1 in the set at 
creation time.  This is probably not worth it from an optimization 
perspective, but as I have learned, the only way to know is to time 
it (and I didn't time it).

  def proper_divisors_sum(n):
  return sum(proper_divisors(n))
  
  def proper_divisors_sorted(n):
  return sorted(proper_divisors(n))
  
  def proper_divisors(n):
  pd = set((1,))
  for x in range(2, int(n**.5)+1):
  factor, mod = divmod(n,x)
  if mod == 0:
  pd.update((x,factor))
  return list(pd)

Have a great day,

-Martin

-- 
Martin A. Brown
http://linux-ip.net/
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] List comprehension question

2010-11-09 Thread Richard D. Moores
On Tue, Nov 9, 2010 at 03:35, Stefan Behnel  wrote:
> Richard D. Moores, 09.11.2010 12:07:
>
> That sqrt(n) works for speeding up the finding of primes, but here we
> want to use int(n/2) (and why didn't I think of that?), which results
> in about a 2x speedup. See.

 NO! Use  int(n/2)+1 .  I'll correct that in
   and report back.
>>>
>>> See
>>>
>>> But now I'll have to redo again using Stefan's ingenious suggestion.
>>
>> Here's what I wrote using Stefan's suggestion:
>>
>> def proper_divisors_sum(n):
>>     pd_list = []
>>     for x in range(1, int(n**.5)+1):
>>         if n % x == 0:
>>             factor = int(x)
>>             factor2 = int(n/factor)
>>             pd_list.extend([factor, factor2])
>>     pd_list = list(set(pd_list))
>>     pd_list.sort()
>>     pd_list = pd_list[:-1]
>>     return sum(pd_list)
>
> Have a look at divmod():
>
> http://docs.python.org/library/functions.html#divmod
>
> Note that you don't need to convert 'x' to an int. It already has that type
> (see the docs on range()). Also, int(n/factor) is the same as n//factor
> here.

From your suggestions I made 2 versions:

def proper_divisors_sum1(n):
pd_list = []
for x in range(1, int(n**.5)+1):
quotient, remainder = divmod(n, x)
if remainder == 0:
pd_list.append(x)
pd_list.append(quotient)
pd_list = list(set(pd_list))
pd_list.sort()
pd_list = pd_list[:-1]
return sum(pd_list)

def proper_divisors_sum2(n):
pd_list = []
for x in range(1, int(n**.5)+1):
if n % x == 0:
pd_list.append(x)
pd_list.append(n//x)
pd_list = list(set(pd_list))
pd_list.sort()
pd_list = pd_list[:-1]
return sum(pd_list)

The first actually slowed down what I had before, but the second made
for a nice speed-up.

Thanks, Stephan.

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


Re: [Tutor] List comprehension question

2010-11-09 Thread Stefan Behnel

Richard D. Moores, 09.11.2010 12:07:

That sqrt(n) works for speeding up the finding of primes, but here we
want to use int(n/2) (and why didn't I think of that?), which results
in about a 2x speedup. See.


NO! Use  int(n/2)+1 .  I'll correct that in
  and report back.


See

But now I'll have to redo again using Stefan's ingenious suggestion.


Here's what I wrote using Stefan's suggestion:

def proper_divisors_sum(n):
 pd_list = []
 for x in range(1, int(n**.5)+1):
 if n % x == 0:
 factor = int(x)
 factor2 = int(n/factor)
 pd_list.extend([factor, factor2])
 pd_list = list(set(pd_list))
 pd_list.sort()
 pd_list = pd_list[:-1]
 return sum(pd_list)


Have a look at divmod():

http://docs.python.org/library/functions.html#divmod

Note that you don't need to convert 'x' to an int. It already has that type 
(see the docs on range()). Also, int(n/factor) is the same as n//factor here.


Stefan

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


Re: [Tutor] List comprehension question

2010-11-09 Thread Richard D. Moores
On Mon, Nov 8, 2010 at 23:49, Richard D. Moores  wrote:
> On Mon, Nov 8, 2010 at 22:47, Richard D. Moores  wrote:
>> On Mon, Nov 8, 2010 at 21:31, Richard D. Moores  wrote:
>>
>>> That sqrt(n) works for speeding up the finding of primes, but here we
>>> want to use int(n/2) (and why didn't I think of that?), which results
>>> in about a 2x speedup. See .
>>
>> NO! Use  int(n/2)+1 .  I'll correct that in
>>  and report back.
>
> See 
>
> But now I'll have to redo again using Stefan's ingenious suggestion.
>
> Dick

Here's what I wrote using Stefan's suggestion:

def proper_divisors_sum(n):
pd_list = []
for x in range(1, int(n**.5)+1):
if n % x == 0:
factor = int(x)
factor2 = int(n/factor)
pd_list.extend([factor, factor2])
pd_list = list(set(pd_list))
pd_list.sort()
pd_list = pd_list[:-1]
return sum(pd_list)

Take a look at the difference in speed his suggestion made, and the
larger n is, the greater the difference:


At n = 100,000,000 the speed improvement over the fastest of the other
3 versions was 2579x!

Employing append() instead of extend() as here:

def proper_divisors_sum(n):
pd_list = []
for x in range(1, int(n**.5)+1):
if n % x == 0:
factor = int(x)
pd_list.append(factor)
factor2 = int(n/factor)
pd_list.append(factor2)
pd_list = list(set(pd_list))
pd_list.sort()
pd_list = pd_list[:-1]
return sum(pd_list)

improves speed by 20% or 30% for large n, but I didn't paste those results.

I'll begin a new thread soon to ask for advice on optimizing a script
that finds amiable pairs, and of course employs proper_divisors_sum().

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


Re: [Tutor] List comprehension question

2010-11-08 Thread Richard D. Moores
On Mon, Nov 8, 2010 at 22:47, Richard D. Moores  wrote:
> On Mon, Nov 8, 2010 at 21:31, Richard D. Moores  wrote:
>
>> That sqrt(n) works for speeding up the finding of primes, but here we
>> want to use int(n/2) (and why didn't I think of that?), which results
>> in about a 2x speedup. See .
>
> NO! Use  int(n/2)+1 .  I'll correct that in
>  and report back.

See 

But now I'll have to redo again using Stefan's ingenious suggestion.

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


Re: [Tutor] List comprehension question

2010-11-08 Thread Richard D. Moores
On Mon, Nov 8, 2010 at 21:31, Richard D. Moores  wrote:

> That sqrt(n) works for speeding up the finding of primes, but here we
> want to use int(n/2) (and why didn't I think of that?), which results
> in about a 2x speedup. See .

NO! Use  int(n/2)+1 .  I'll correct that in
 and report back.

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


Re: [Tutor] List comprehension question

2010-11-08 Thread Stefan Behnel

Richard D. Moores, 09.11.2010 06:31:

On Mon, Nov 8, 2010 at 03:43, Steven D'Aprano wrote:

Richard D. Moores wrote:



Coming back to your function:

def proper_divisors(n):
sum_ = 0
for x in range(1,n):
if n % x == 0:
sum_ += x
return sum_

we can write that much more simply:

def proper_divisors(n):
return sum(x for x in range(1, n) if n%x == 0)


And we can speed it up a bit by realising that there's no need to go all the
way up to n in the range. After all, we know that (say) 100%96 can't
possibly be zero. The largest factor of n is sqrt(n):

def proper_divisors(n):
return sum(x for x in range(1, int(math.sqrt(n))) if n%x == 0)


For large n, that will save a lot of time.


That sqrt(n) works for speeding up the finding of primes, but here we
want to use int(n/2) (and why didn't I think of that?), which results
in about a 2x speedup.


Ah, good catch. Another lesson learned:

When you optimise, make sure you have good unit test coverage that proves 
you didn't break anything by trying to make things faster.


But Steven is right in that it's enough to run up to sqrt(n). You can 
improve things again by collecting not only the divisor you find but also 
its counterpart factor at the same time, i.e. when you find out that 2 is a 
divisor of n, add both 2 and n/2.


Then the point to stop is really sqrt(n).

Finally, sorting the resulting list will be a quick operation compared to 
finding the divisors.


Stefan

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


Re: [Tutor] List comprehension question

2010-11-08 Thread Richard D. Moores
On Mon, Nov 8, 2010 at 03:43, Steven D'Aprano  wrote:
> Richard D. Moores wrote:

> Coming back to your function:
>
> def proper_divisors(n):
>    sum_ = 0
>    for x in range(1,n):
>        if n % x == 0:
>            sum_ += x
>    return sum_
>
>
> we can write that much more simply:
>
> def proper_divisors(n):
>    return sum(x for x in range(1, n) if n%x == 0)
>
>
> And we can speed it up a bit by realising that there's no need to go all the
> way up to n in the range. After all, we know that (say) 100%96 can't
> possibly be zero. The largest factor of n is sqrt(n):
>
>
> def proper_divisors(n):
>    return sum(x for x in range(1, int(math.sqrt(n))) if n%x == 0)
>
>
> For large n, that will save a lot of time.

That sqrt(n) works for speeding up the finding of primes, but here we
want to use int(n/2) (and why didn't I think of that?), which results
in about a 2x speedup. See .

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


Re: [Tutor] List comprehension question

2010-11-08 Thread Steven D'Aprano

Stefan Behnel wrote:

Hugo Arts, 08.11.2010 00:53:

[...]

On another note, getting rid of the list comprehension and using a
generator expression will be even faster, since you won't have to
build the list.


I gave this suggestion a try. It is true for me when run in CPython 3.2:

[...]

However, it is no longer true when I run the same thing in Cython:

[...]

Lesson learned:

Sometimes, it can be worth splitting a loop in two, one with a tight 
filter for the values, and another one to work on the remaining values.


Nice analysis, thank you. However, surely the most important lesson to 
be learned is:


Don't make assumptions about what is faster, measure it and find out!



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


Re: [Tutor] List comprehension question

2010-11-08 Thread Steven D'Aprano

Alan Gauld wrote:


"Steven D'Aprano"  wrote

I'm going to be pedantic here... but to quote the Middleman, 
specificity is the soul of all good communication.


Be pedantic! :-)
I really liked the explanation although I already sort of knew most of it.
But there were a few nuggets in there I'd missed, like range() being
a type all of its own.


Thank you :)


But one, slightly off-topic, question:


def proper_divisors(n):
return sum(x for x in range(1, int(math.sqrt(n))) if n%x == 0)



Why use math.sqrt() instead of just using the ** operator?

return sum(x for x in range(1, int(n**0.5)) if n%x == 0)

I'd have expected ** to be significantly faster than calling the
function, and given this is a performance tweak...?



Mostly personal taste, but I would expect math.sqrt() to be more 
accurate than a generic exponentiation operator, although in this case 
the difference shouldn't matter. If your value for n is so large that 
you need to care about the floating point rounding errors in n**0.5, 
you're probably using the wrong tool.


As for the speed, sqrt() only gets called once, so the difference 
shouldn't matter. But for what it's worth:


[st...@sylar ~]$ python3 -m timeit -s "import math" "math.sqrt(1234567)"
100 loops, best of 3: 0.486 usec per loop
[st...@sylar ~]$ python3 -m timeit "1234567**0.5"
100 loops, best of 3: 0.265 usec per loop

So on my machine, the overhead of calling a function is about 0.2 
micro-seconds. Compare that to:


[st...@sylar ~]$ python3 -m timeit -s "n=1234567" "sum(x for x in 
range(1, int(n**0.5)) if n%x == 0)"

1000 loops, best of 3: 515 usec per loop


So changing from math.sqrt(n) to n**0.5 increases the overall speed by 
approximately 0.04%. Truly a micro-optimization :)



(I'm deliberately not including the time to import math here. I assume 
that the function proper_divisors() will be in a module with other maths 
related functions, and therefore you need to import it regardless.)




--
Steven

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


Re: [Tutor] List comprehension question

2010-11-08 Thread Alan Gauld


"Stefan Behnel"  wrote


On another note, getting rid of the list comprehension and using a
generator expression will be even faster, since you won't have to
build the list.


I gave this suggestion a try. It is true for me when run in CPython 
3.2:


However, it is no longer true when I run the same thing in Cython:
...
Lesson learned:

Sometimes, it can be worth splitting a loop in two, one with a tight 
filter for the values, and another one to work on the remaining 
values.


And another good example of how hard it is to guess the optimal
solution in performance terms. It is one area where nothing beats
trial and test. And another reason why premature optimisation should
be resisted! :-)

Alan G. 



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


Re: [Tutor] List comprehension question

2010-11-08 Thread Alan Gauld


"Stefan Behnel"  wrote


Why use math.sqrt() instead of just using the ** operator?

return sum(x for x in range(1, int(n**0.5)) if n%x == 0)

Since this operation is only evaluated once in the whole runtime of 
the loop, I think readability beats the likely very tiny performance 
difference here.


Ah, I wondered if readability was the reason. I hadn't thought about
it hard enough to notice the sqrt() would only be called once! :-)

As to readability I personally prefer the exponentiation sign (or even 
pow()!)

and don't think I have ever used math.sqrt() in my 12 years of Python.
But I recognise that some may prefer sqrt, especially if they don't
have a math background.

Alan G. 



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


Re: [Tutor] List comprehension question

2010-11-08 Thread Stefan Behnel

Hugo Arts, 08.11.2010 00:53:

On Mon, Nov 8, 2010 at 12:36 AM, Richard D. Moores wrote:

def proper_divisors(n):
 """
 Return the sum of the proper divisors of positive integer n
 """
 return sum([x for x in range(1,n) if int(n/x) == n/x])

The list comprehension is this function is inefficient in that it computes
n/x twice. I'd like to do an  a = n/x and use a in
"if int(a) == a", but I don't know how.



You can't do that inside a list comprehension. Either get rid of the
comprehension and do a regular loop, or get rid of the n/x expression.

I'd suggest replacing the whole check with x % n == 0. n is a proper
divisor of x if there is no remainder after division, after all. This
also means you won't have to do a cast, which tend to be fairly
expensive.

On another note, getting rid of the list comprehension and using a
generator expression will be even faster, since you won't have to
build the list.


I gave this suggestion a try. It is true for me when run in CPython 3.2:

$ python3 -m timeit -s 'from divisors import forloop' 'forloop(100)'
10 loops, best of 3: 161 msec per loop
$ python3 -m timeit -s 'from divisors import genexp' 'genexp(100)'
10 loops, best of 3: 159 msec per loop
$ python3 -m timeit -s 'from divisors import listcomp' 'listcomp(100)'
10 loops, best of 3: 171 msec per loop

However, it is no longer true when I run the same thing in Cython:

$ python3 -m timeit -s 'from divisors import forloop' 'forloop(100)'
100 loops, best of 3: 13.6 msec per loop
$ python3 -m timeit -s 'from divisors import genexp' 'genexp(100)'
100 loops, best of 3: 13.6 msec per loop
$ python3 -m timeit -s 'from divisors import listcomp' 'listcomp(100)'
100 loops, best of 3: 12.6 msec per loop

Here, the listcomp clearly wins, i.e.

return sum([x for x in range(1,n) if n%x == 0])

is actually *faster* than the inlined loop for

result = sum(x for x in range(1,n) if n%x == 0)
return result

This totally surprised me, until I figured out what was going on here.

In the case of the listcomp, the inner loop is smaller, it does not contain 
the adding. It only contains the division that filters out the 
non-divisors. Then, from time to time, it calls into the list appender to 
append a Python integer that actually matched the condition. But the final 
list is tiny, so this is done extremely rarely compared to the number of 
loop iterations. The tighter loop simply wins. And summing up a short list 
in another tight loop is just another very fast operation.


Lesson learned:

Sometimes, it can be worth splitting a loop in two, one with a tight filter 
for the values, and another one to work on the remaining values.


Stefan

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


Re: [Tutor] List comprehension question

2010-11-08 Thread Stefan Behnel

Alan Gauld, 08.11.2010 17:28:

"Steven D'Aprano" wrote

def proper_divisors(n):
return sum(x for x in range(1, int(math.sqrt(n))) if n%x == 0)


Why use math.sqrt() instead of just using the ** operator?

return sum(x for x in range(1, int(n**0.5)) if n%x == 0)

I'd have expected ** to be significantly faster than calling the
function, and given this is a performance tweak...?


Since this operation is only evaluated once in the whole runtime of the 
loop, I think readability beats the likely very tiny performance difference 
here.


Stefan

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


Re: [Tutor] List comprehension question

2010-11-08 Thread Alan Gauld


"Steven D'Aprano"  wrote

I'm going to be pedantic here... but to quote the Middleman, 
specificity is the soul of all good communication.


Be pedantic! :-)
I really liked the explanation although I already sort of knew most of 
it.

But there were a few nuggets in there I'd missed, like range() being
a type all of its own.

But one, slightly off-topic, question:


def proper_divisors(n):
return sum(x for x in range(1, int(math.sqrt(n))) if n%x == 0)



Why use math.sqrt() instead of just using the ** operator?

return sum(x for x in range(1, int(n**0.5)) if n%x == 0)

I'd have expected ** to be significantly faster than calling the
function, and given this is a performance tweak...?

--
Alan Gauld
Author of the Learn to Program web site
http://www.alan-g.me.uk/


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


Re: [Tutor] List comprehension question

2010-11-08 Thread Steven D'Aprano

Richard D. Moores wrote:


So this version of my function uses a generator, range(), no?

def proper_divisors(n):
sum_ = 0
for x in range(1,n):
if n % x == 0:
sum_ += x
return sum_


I'm going to be pedantic here... but to quote the Middleman, specificity 
is the soul of all good communication.


The term "generator" in Python refers specifically to an object akin to 
ordinary functions. Instead of using return, they use yield:


def g(n):
n = 2*n
yield n
yield n+1

g itself is a "generator function", and the result of calling g is a 
"generator object". In practice, people tend to be sloppy and just refer 
to both the function g and the result of calling it as generators, 
expecting the reader to tell from context which is which.


But pedantically, we can see the difference:

>>> g  # the function itself

>>> type(g)

>>> g(1)  # the result of calling the function

>>> type(g(1))


Generators are a special type of "iterators" -- iterators are objects 
which can be iterated over, like lists, strings, and many others. In 
this case, the generator is a special type of executable function which 
can be paused mid-process. If you do this:


it = g(3)  # say
next(it)

the built-in next() function starts executing the generator object. The 
code is executed up to the first yield statement:


n = 2*n
yield n

and so next(it) returns 2*3 = 6. Then execution pauses, and the 
generator just waits.


(Aside: in Python 2.x, next(it) is written it.next() instead.)

The next time you call next(it), execution continues until the next yield:

yield n+1

and so next(it) will now return 6+1 = 7.

Finally, if you call next(it) again, execution drops off the end of the 
code, and the generator will raise StopIteration.


Now, this seems a bit complicated, but Python can handle most of that 
for you. Instead of manually calling next() on the generator object, if 
you use it in a for-loop:


for i in g(3):
print(i)

the for-loop will handle calling next and catching the StopIterator, and 
you simply see i = 6, 7. Or you can pass it to functions such as list:


list(g(3))

and get pretty much the same result.

(For advanced use: in newer versions of Python, generators have become 
even more powerful, but complex, objects called co-routines. Co-routines 
allow you to send data *into* the middle of the running code, as well as 
extract data using yield.)


Python also has "generator expressions" -- this is a short-cut syntax 
for particularly simple generators. Generator expressions look just like 
list expressions, except they use round brackets instead of square:


>>> (x+1 for x in (1, 2, 4) if x%2 == 0)
 at 0xb7a7be3c>

List comprehensions run all the way to the end, producing a list. 
Generator expressions run lazily, only producing values one at a time as 
needed. So compare:


sum([list comp]) vs sum(gen expr)

The first case needs to find storage for the entire list first, which is 
potentially huge. But the second case just adds the numbers one at a 
time, and so never needs much memory.


So, that's generators... what about range? range is also an iterator, 
that is, something you can iterate over, but it's not a generator:


>>> type(range(20))


It is its own special type of object, like list, str, int or dict.


Coming back to your function:

def proper_divisors(n):
sum_ = 0
for x in range(1,n):
if n % x == 0:
sum_ += x
return sum_


we can write that much more simply:

def proper_divisors(n):
return sum(x for x in range(1, n) if n%x == 0)


And we can speed it up a bit by realising that there's no need to go all 
the way up to n in the range. After all, we know that (say) 100%96 can't 
possibly be zero. The largest factor of n is sqrt(n):



def proper_divisors(n):
return sum(x for x in range(1, int(math.sqrt(n))) if n%x == 0)


For large n, that will save a lot of time.




--
Steven

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


Re: [Tutor] List comprehension question

2010-11-07 Thread Richard D. Moores
On Sun, Nov 7, 2010 at 17:47, Wayne Werner  wrote:
> On Sun, Nov 7, 2010 at 7:15 PM, Richard D. Moores 
> wrote:
>>
>> On Sun, Nov 7, 2010 at 16:41, Wayne Werner  wrote:
>> > On Sun, Nov 7, 2010 at 6:31 PM, Hugo Arts  wrote:
>> 
>> I should have mentioned that I'm using 3.1 .
>>
>> So this version of my function uses a generator, range(), no?
>
> Correct. The rule of thumb for this type of thing is that if you care about
> the entire object/collection, you should use a listcomp (or range in 2.x),
> but if you only care about individual elements you should always use a
> generator. Your function is a perfect example of this - you only care about
> the individual #s from 1 up to n, not the collection of numbers as a whole,
> so a generator is what you should prefer.
>
>>
>> def proper_divisors(n):
>>    sum_ = 0
>>    for x in range(1,n):
>>        if n % x == 0:
>>            sum_ += x
>>    return sum_
>
> Generators are super powerful, and my preferred reference on the subject is
> here: www.dabeaz.com/generators/



Thank you for the advice and the link.

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


Re: [Tutor] List comprehension question

2010-11-07 Thread Wayne Werner
On Sun, Nov 7, 2010 at 7:15 PM, Richard D. Moores wrote:

> On Sun, Nov 7, 2010 at 16:41, Wayne Werner  wrote:
> > On Sun, Nov 7, 2010 at 6:31 PM, Hugo Arts  wrote:
> 
> I should have mentioned that I'm using 3.1 .
>
> So this version of my function uses a generator, range(), no?
>

Correct. The rule of thumb for this type of thing is that if you care about
the entire object/collection, you should use a listcomp (or range in 2.x),
but if you only care about individual elements you should always use a
generator. Your function is a perfect example of this - you only care about
the individual #s from 1 up to n, not the collection of numbers as a whole,
so a generator is what you should prefer.


>
> def proper_divisors(n):
>sum_ = 0
>for x in range(1,n):
>if n % x == 0:
>sum_ += x
>return sum_
>

Generators are super powerful, and my preferred reference on the subject is
here: www.dabeaz.com/*generators*/

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


Re: [Tutor] List comprehension question

2010-11-07 Thread Richard D. Moores
On Sun, Nov 7, 2010 at 16:41, Wayne Werner  wrote:
> On Sun, Nov 7, 2010 at 6:31 PM, Hugo Arts  wrote:
>>
>> 
>> here's a list comprehension
>> >>> a = [x*2 for x in range(10)]
>> >>> a
>> [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
>>
>> here's the equivalent generator expression:
>> >>> a = (x*2 for x in range(10))
>>
>>  
>
> Since you're talking about generators and efficiency, it's probably a good
> idea to point out that range is only a generator in python 3.x. In python
> 2.x it creates a list.

I should have mentioned that I'm using 3.1 .

So this version of my function uses a generator, range(), no?

def proper_divisors(n):
sum_ = 0
for x in range(1,n):
if n % x == 0:
sum_ += x
return sum_

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


Re: [Tutor] List comprehension question

2010-11-07 Thread Alan Gauld


"Hugo Arts"  wrote


Yes. A cast or typecast means converting some data to a different
type, like converting floats to integers, strings to integers,


The term cast can be misleading however since in some
languages - those decended from C it means treating a piece
of data as if it were another type, which is different to converting 
it.


For example in C:

char c = '7';
int x = (int)c;  //this is type casting in C - it means treat c as 
an integer

int y = atoi(c);   // this is type conversion in C

x and y are not the same. x is effectively ord('7') whereas y is 7.
But in C only the first is referred to as a cast.

Not directly relevant in a Python thread but it can cause confusion
if newbies see references to casting in the C sense and think
it means type conversion.

Just feeling picky,

--
Alan Gauld
Author of the Learn to Program web site
http://www.alan-g.me.uk/





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


Re: [Tutor] List comprehension question

2010-11-07 Thread Wayne Werner
On Sun, Nov 7, 2010 at 6:31 PM, Hugo Arts  wrote:

> 
> here's a list comprehension
> >>> a = [x*2 for x in range(10)]
> >>> a
> [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
>
> here's the equivalent generator expression:
> >>> a = (x*2 for x in range(10))

 


Since you're talking about generators and efficiency, it's probably a good
idea to point out that range is only a generator in python 3.x. In python
2.x it creates a list.

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


Re: [Tutor] List comprehension question

2010-11-07 Thread Hugo Arts
On Mon, Nov 8, 2010 at 1:16 AM, Richard D. Moores  wrote:
> On Sun, Nov 7, 2010 at 15:53, Hugo Arts  wrote:
>> n is a proper
>> divisor of x if there is no remainder after division, after all. This
>> also means you won't have to do a cast, which tend to be fairly
>> expensive.
>
> I don't know what a cast is. Would that be the int(n/x)?
>

Yes. A cast or typecast means converting some data to a different
type, like converting floats to integers, strings to integers,
integers to strings, etc. They are fairly expensive because the
representation of the data changes.

> Here are 2 versions, of about equal speed:
>
> def proper_divisors(n):
>    """
>    Return the sum of the proper divisors of positive integer n
>    """
>    return sum([x for x in range(1,n) if n % x == 0])
>
> def proper_divisors(n):
>    sum_ = 0
>    for x in range(1,n):
>        if n % x == 0:
>            sum_ += x
>    return sum_
>
>> On another note, getting rid of the list comprehension and using a
>> generator expression will be even faster, since you won't have to
>> build the list.
>
> Could you spell that out for me?

here's a list comprehension
>>> a = [x*2 for x in range(10)]
>>> a
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]

here's the equivalent generator expression:
>>> a = (x*2 for x in range(10))
>>> a
 at 0xb7792fa4>
>>> for x in a: print x
0
2
4
6
8
10
12
14
16
18

As you can see, they are constructed almost the same way, the only
difference being the type of parentheses. The main difference is what
comes out. A list comprehension computes all its elements and builds a
list out of them, very simple.

A generator expression builds a generator. When you create a
generator, nothing is actually done yet. Only when you *iterate* over
a generator (like I did with the for loop) does it start computing
results, one by one, giving each one out as it is needed.

If all you're doing with the results is iterating over them once and
then throwing them away (like you do here with sum()), using a
generator expression saves us some time and space, since we don't have
to build a list object that we won't be needing anyway.

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


Re: [Tutor] List comprehension question

2010-11-07 Thread Richard D. Moores
On Sun, Nov 7, 2010 at 15:53, Hugo Arts  wrote:
> On Mon, Nov 8, 2010 at 12:36 AM, Richard D. Moores  wrote:
>> def proper_divisors(n):
>>     """
>>     Return the sum of the proper divisors of positive integer n
>>     """
>>     return sum([x for x in range(1,n) if int(n/x) == n/x])
>>
>> The list comprehension is this function is inefficient in that it computes
>> n/x twice. I'd like to do an  a = n/x and use a in
>> "if int(a) == a", but I don't know how.
>>
>
> You can't do that inside a list comprehension. Either get rid of the
> comprehension and do a regular loop, or get rid of the n/x expression.
>
> I'd suggest replacing the whole check with x % n == 0.

Wow! using n % x == 0 is about 3x faster than what I had before.

> n is a proper
> divisor of x if there is no remainder after division, after all. This
> also means you won't have to do a cast, which tend to be fairly
> expensive.

I don't know what a cast is. Would that be the int(n/x)?

Here are 2 versions, of about equal speed:

def proper_divisors(n):
"""
Return the sum of the proper divisors of positive integer n
"""
return sum([x for x in range(1,n) if n % x == 0])

def proper_divisors(n):
sum_ = 0
for x in range(1,n):
if n % x == 0:
sum_ += x
return sum_

> On another note, getting rid of the list comprehension and using a
> generator expression will be even faster, since you won't have to
> build the list.

Could you spell that out for me?

Thanks,

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


Re: [Tutor] List comprehension question

2010-11-07 Thread Hugo Arts
On Mon, Nov 8, 2010 at 12:36 AM, Richard D. Moores  wrote:
> def proper_divisors(n):
>     """
>     Return the sum of the proper divisors of positive integer n
>     """
>     return sum([x for x in range(1,n) if int(n/x) == n/x])
>
> The list comprehension is this function is inefficient in that it computes
> n/x twice. I'd like to do an  a = n/x and use a in
> "if int(a) == a", but I don't know how.
>

You can't do that inside a list comprehension. Either get rid of the
comprehension and do a regular loop, or get rid of the n/x expression.

I'd suggest replacing the whole check with x % n == 0. n is a proper
divisor of x if there is no remainder after division, after all. This
also means you won't have to do a cast, which tend to be fairly
expensive.

On another note, getting rid of the list comprehension and using a
generator expression will be even faster, since you won't have to
build the list.

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


[Tutor] List comprehension question

2010-11-07 Thread Richard D. Moores
def proper_divisors(n):
"""
Return the sum of the proper divisors of positive integer n
"""
return sum([x for x in range(1,n) if int(n/x) == n/x])

The list comprehension is this function is inefficient in that it computes
n/x twice. I'd like to do an  a = n/x and use a in
"if int(a) == a", but I don't know how.

Thanks,

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


<    1   2   3   4   5   6   7   8   >