Re: [Tutor] Python functions are first-class citizens
On 07/31/2014 11:46 PM, Ben Finney wrote: The ‘max’ function can be told how to determine the ordering of items, by specifying a key parameter. The parameter is specified by giving a value; that value is a function. Hmmm... might just have had a break-thru here: so max() iterates thru counts, which because its the only non-keyword argument provided has to be an iterable (if I'm reading this correctly: https://docs.python.org/3/library/functions.html?highlight=max#max). It takes each dict key ('a', 'b', 'c'), feeds them in turn to counts.get() like so: counts.get('a'), counts.get('b'), counts.get('c'), which should return the corresponding dict values (1, 22, 100), and then max() returns the highest value seen. Is that about right? Monte -- Shiny! Let's be bad guys. Reach me @ memilanuk (at) gmail dot com ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Using subprocess on a series of files with spaces
C Smith wrote: > Nice, these are useful tools. I have been building something with just > basic stuff and avoiding learning any libraries. If I wanted to get > some insight on a larger program that is about 1000 lines, would that > be doable here? In general we prefer concrete questions and smaller chunks of code. With 1000 lines you get fewer people to even take a look. You might still try and post a link to the code together with a few questions here... ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Python functions are first-class citizens
memilanuk writes: > On 07/31/2014 11:46 PM, Ben Finney wrote: > > > The ‘max’ function can be told how to determine the ordering of > > items, by specifying a key parameter. The parameter is specified by > > giving a value; that value is a function. > > Hmmm... might just have had a break-thru here: so max() iterates thru > counts No. You should not expect ‘max’ to iterate through anything. All it does is compute, somehow, which item in the collection is largest. Iteration isn't relevant to that. I'm being a stickler on this point because “iterate” implies something quite specific in Python, and this behaviour is not implied by the purpose of ‘max’. Instead, think only “finds the largest item in the collection”. > which because its the only non-keyword argument provided has to be an > iterable (if I'm reading this correctly: > https://docs.python.org/3/library/functions.html?highlight=max#max). You're reading that right. I consider that document a bit confusing, though; I would prefer instead that it says “collection”, because whether the collection is iterable shouldn't matter. > It takes each dict key ('a', 'b', 'c') Ah! Now I get a better idea why you're confused. There are two distinct uses of “key” going on. The dict has a key for each item, so called because the key is used to access a specific item in the dict. The ‘max’ operation needs a defined algorithm to determine which of two items is larger. It calls this algorithm the “key function”, because this is the same terminology used when sorting the collection. So ‘max’ takes an optional function as the “key function”, which is named ‘key’. But those two uses are distinct, and the “key function” for determining order in a sequence doesn't really relate to the key of a dict item. The terminology in computing often has conflicting uses of the same word; “key” is unfortunately one of those words. > feeds them in turn to counts.get() like so: counts.get('a'), > counts.get('b'), counts.get('c'), which should return the > corresponding dict values (1, 22, 100), and then max() returns the > highest value seen. > > Is that about right? Roughly, except: * Computing the largest item doesn't imply iteration at all, so it's misleading to think of “iterate” at all. The ‘max’ function has as its first argument a collection, whether that collection is iterable or not. * There is no guarantee all the items will be seen. ‘max’ could very well decide it's got the largest item and return it at any point. It's an implementation detail how it does that. * The “key function” expected by ‘max’ in its ‘key’ parameter has no real relation to the key of a dictionary item, except by coincidence here. Broadly, you should consider the ‘max’ function a black box. (It's not, though, and if you're *really* curious you can inspect the source code of your particular Python implementation and see one possible way of doing it — bearing in mind that there's no guarantee it will be implemented the same way anywhere else.) When you call the ‘max’ function, don't think of it doing any specific sequence of steps. You specify a collection of items; you may specify a key function to be used for determining which of two items is the larger. The result is that ‘max’ uses the specified key function to compute the largest item from the specified collection, and returns that item. -- \ “Those who write software only for pay should go hurt some | `\ other field.” —Erik Naggum, in _gnu.misc.discuss_ | _o__) | Ben Finney ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Using subprocess on a series of files with spaces
Peter Otten <__pete...@web.de> writes: > C Smith wrote: > > > Nice, these are useful tools. I have been building something with > > just basic stuff and avoiding learning any libraries. If I wanted to > > get some insight on a larger program that is about 1000 lines, would > > that be doable here? > > In general we prefer concrete questions and smaller chunks of code. > With 1000 lines you get fewer people to even take a look. Right. When attrmpting to learn, keep the examples simple. This will make it easier to focus on the essential points, and also minimise whole categories of error. To get feedback on some code, make it a Short, Self-Contained, Compilable Example http://sscce.org/>. This means we will be able to read the code quickly, run it ourselves, and better see what its purpose is. > You might still try and post a link to the code together with a few > questions here... Not really advised. If the code is too long to discuss in context here, much of the point is lost; we prefer discussions to have the code inline so the public archives contain the code too. That's an important reason to keep it short and self-contained. -- \ “I bought some batteries, but they weren't included; so I had | `\to buy them again.” —Steven Wright | _o__) | Ben Finney ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Python functions are first-class citizens
On 08/01/2014 01:33 AM, Ben Finney wrote: Ah! Now I get a better idea why you're confused. There are two distinct uses of “key” going on. Ahhh... no. Yes, I realize there were two different uses of 'key' and no, I didn't think they were necessarily the same. * There is no guarantee all the items will be seen. ‘max’ could very well decide it's got the largest item and return it at any point. It's an implementation detail how it does that. What?!? Are you serious? Under what kind of conditions? Broadly, you should consider the ‘max’ function a black box. Yeah, I'm starting to see that... -- Shiny! Let's be bad guys. Reach me @ memilanuk (at) gmail dot com ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
[Tutor] capturing errors/exceptions..
Hi. Really basic question!! Got a chunk of some test python, trying to figure out a quick/easy way to capture all/any errors/exceptions that get thrown.. For the test process, I need to "ensure" that I capture any/all potential errors.. -Could/Should I wrap the entire func in a try/catch when I call the function from the parent process? -Should I have separate try/catch blocks within the function? -The test py app is being run from the CLI, is there a py command line attribute that auto captures all errors? Any thoughts.. Thanks! A sample of the test code is: def getParseCollegeFacultyList1(url, content): s=content s=s.replace(" ","") if(debug==1): print "s="+s url=url.strip("/") #got the page/data... parse it and get the "schools".. #use the "dept" list as the school # s contains HTML not XML text d = libxml2dom.parseString(s, html=1) ### #-- #--create the output data file for the registrar/start data #-- #-- ### #term_in=201336&&sel_subj=ACCT if(debug==1): print "inside parse state/college function \n" #---Form #fetch the option val/text for the "depts" which are used #as the dept abbrv/name on the master side #-- the school matches the dept... #-- this results in separate packets for each dept p="//a[contains(@href,'SelectTeacher') and @id='last']//attribute::href" ap="//a[contains(@href,'campusRatings.jsp')]//attribute::href" hpath="//div[@id='profInfo']/ul/li[1]//a/attribute::href"# -get the college website cpath="//div[@id='profInfo']/ul/li[2]/text()" #-get the city,state colpath="//h2/text()"#-college name xpath="//a[contains(@title,'school id:')]/attribute::href" hh_ = d.xpath(hpath) cc_ = d.xpath(cpath) col_ = d.xpath(colpath) ap_ = d.xpath(ap) if(debug==1): print "hhl "+str(len(hh_)) print "ccl "+str(len(cc_)) web="" if (len(hh_)>0): web=hh_[0].textContent city="" if (len(cc_)>0): city=cc_[0].textContent colname="" if (len(col_)>0): colname=col_[0].textContent colname=colname.encode('ascii', 'ignore').strip() # # set up out array # ret={} out={} row={} jrow="" ndx=0 pcount_ = d.xpath(p) if(len(pcount_)==0): #at least one success/entry.. but apparently only a single page.. status=True #count=pcount_[0].textContent.strip() #countp=count.split('&pageNo=') #count=countp[1] #rr=countp[0] if(len(ap_)==1): idd=ap_[0].textContent.strip() idd=idd.split("?sid=") idd=idd[1].split("&") idd=idd[0].strip() nurl=url+"/SelectTeacher.jsp?sid="+idd+"&pageNo=1" #nurl=url+"&pageNo=1" row={} row['WriteData']=True row['tmp5']=web row['tmp6']=city row['tmp7']=colname row['tmp8']=nurl #don't json for now #jrow=simplejson.dumps(row) jrow=row out[ndx]=jrow ndx = ndx+1 else: #at least one success/entry.. set the status status=True count=pcount_[0].textContent.strip() countp=count.split('&pageNo=') count=countp[1] rr=countp[0] if(debug==1): print "c ="+str(count)+"\n" for t in range(1,int(count)+1): nurl=url+rr+"&pageNo="+str(t) if(debug==1): print "nurl = "+nurl+"\n" row={} row['WriteData']=True row['tmp5']=web row['tmp6']=city row['tmp7']=colname row['tmp8']=nurl #don't json for now #jrow=simplejson.dumps(row) jrow=row out[ndx]=jrow ndx = ndx+1 ret['data']=simplejson.dumps(out) ret['count']=ndx ret['status']=status return(ret) ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Python functions are first-class citizens
On Fri, Aug 01, 2014 at 02:37:43AM -0700, memilanuk wrote: > On 08/01/2014 01:33 AM, Ben Finney wrote: > >* There is no guarantee all the items will be seen. ‘max’ could very > > well decide it's got the largest item and return it at any point. It's > > an implementation detail how it does that. > > What?!? Are you serious? Under what kind of conditions? Imagine a type of list which keeps a record of the largest value currently inside the list. Each time you append a new value, it compares it to the current "largest", and if bigger, changes the largest to the new value. (How you handle deletions is left as an exercise.) With this implementation, max(my_custom_list) is in principle a single, constant-time, lookup. I say in principle because I don't think Python provides any hooks for max() to take short cuts like this. But it could. Or perhaps the list is guaranteed to be sorted, in which case the max value is always the first; or you're scanning a tree, not a list, and you can find the maximum value much more efficiently than inspecting every element. Or you have a parallel processing computer which can compare all N elements and find the maximum in a single machine cycle. The point Ben is making is that one does not usually need to understand the implementation of the function to understand how to use it. Having said this, though, I find myself disagreeing with Ben's strict "ignore the implementation" stance. I sometimes find that I cannot really understand how to use a function until I've understood the algorithm it uses. It's not necessary to understand every last detail of it's implementation, but at least understanding the algorithm is useful. E.g. I don't understand the implementation of Python dicts, but I understand that they are a hash table with (I believe) linear probing, which makes it easy to see that dict look-ups are approximately constant time, degrading to linear time if all the keys have the same hash value. -- Steven ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Python functions are first-class citizens
On Thu, Jul 31, 2014 at 10:12:49PM -0700, memilanuk wrote: > Been reading a bit more in the mean time, trying to grok that 'key' > parameter for max()... and of course the python docs for max(iterable, > key=) refer to the docs for list.sort() ;) > > Kind of diverging off the original question a bit... but since it did > include the max() code in it... I'm having a bit of difficulty with the > whole 'key=' parameter when combined with counts.get here. To understand the key parameter, it helps to know a bit of history. Back in the Dark Ages, list.sort() didn't have a key parameter. It did, however, have a cmp parameter, but I'm going to ignore that because it worked in a completely different way, not relevant to this discussion. Suppose you wanted to do a case-insensitive sort. This was one way: data = ['narwhal', 'cat', 'DOG', 'FOX', 'lion', 'cow', 'APE', 'WALRUS'] # Make a copy of the data, recording the lower-cased values. data2 = [] for item in data: data2.append( (item.lower(), item) ) # Sort this "decorated" version. data2.sort() # Remove the lower-cased values. for i in range(len(data)): data[i] = data2[i][1] which we can write more concisely using list comprehensions: data = ['narwhal', 'cat', 'DOG', 'FOX', 'lion', 'cow', 'APE', 'WALRUS'] # Decorate: data = [(value.lower(), value) for value in data] # Sort: data.sort() # Undecorate: data = [value[1] for value in data] print data => ['APE', 'cat', 'cow', 'DOG', 'FOX', 'lion', 'narwhal', 'WALRUS'] (Wow, that brings back memories...) This is called "Decorate/Sort/Undecorate", or DSU, or sometimes "Schwartzian Transform" after a Perl programmer, Randal L. Schwartz, who popularised it. (The basic idea is *much* older than Perl.) Now, the important part is the "decorate" step. In this case, we decorate the values by calling the str.lower() method on the value. That's the only part of the process which differs depending on the data being compared, everything else: * making the tuples (transform(item), item) * sorting the subsequent list * extracting out the original items again can be handled automatically. So much so that around Python 2.3 or 2.4, list.sort() and the sorted() function gained the ability to perform DSU automatically. All you have to do is provide the transformation function, which by tradition is called a "key function", hence the argument is called "key". data = ['narwhal', 'cat', 'DOG', 'FOX', 'lion', 'cow', 'APE', 'WALRUS'] data.sort(key=str.lower) print data => ['APE', 'cat', 'cow', 'DOG', 'FOX', 'lion', 'narwhal', 'WALRUS'] We can apply this DSU idiom to maximum and minimum as well. Suppose we want to find the string with the maximum length: data = ['narwhal', 'cat', 'DOG', 'FOX', 'lion', 'cow', 'APE', 'WALRUS'] # Decorate: data2 = [(len(s), s) for s in data] # Find the maximum: x = max(data2) # Undecorate: x = x[1] print x => 'narwhal' So, max() and min() have also gained a key argument: max(data, key=len) => 'narwhal' [...] > Where things are going pear-shaped is how counts.get can function as a > 'key' when we don't actually supply () (or anything inside them) to > specify what k,v pair we want, and how that relates back to the iterable > for max(), counts? You don't have to provide the parentheses because Python does so for you. -- Steven ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] capturing errors/exceptions..
On Fri, Aug 01, 2014 at 10:14:38AM -0400, bruce wrote: > Hi. > > Really basic question!! > > Got a chunk of some test python, trying to figure out a quick/easy way > to capture all/any errors/exceptions that get thrown.. Why do you want to do that? The answer to your question will depend on what you expect to do with the exception once you've caught it, and the answer might very well be "don't do that". > For the test process, I need to "ensure" that I capture any/all > potential errors.. Hmmm. I don't quite see the reason for this. If you're running by hand, manually, surely you want to see the exceptions so that you can fix them? If there's an exception, what do you expect to do next? If you're using the unittest module, it already captures the exceptions for you, no need to re-invent the wheel. > -Could/Should I wrap the entire func in a try/catch when I call the > function from the parent process? You mean something like this? try: mymodule.function_being_test(x, y, z) except Exception: do_something_with_exception() Sure. Sounds reasonable, if you have something reasonable to do once you've captured the exception. > -Should I have separate try/catch blocks within the function? No. That means that the function is constrained by the testing regime. > -The test py app is being run from the CLI, is there a py command line > attribute that auto captures all errors? No. How would such a thing work? In general, once an exception occurs, you get a cascade of irrelevant errors: n = lne(some_data) # Oops I meant len m = 2*n + 1 # oops, this fails because n doesn't exist value = something[m] # now this fails because m doesn't exist ... Automatically recovering from an exception and continuing is not practical, hence Python halts after an exception unless you take steps to handle it yourself. -- Steven ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Using subprocess on a series of files with spaces
>However, the subprocess call above uses a list for the command, and that form >DOES NOT pass anything to the shell. The >command gets executed directly. And >therefore no spaces need escaping at all. That makes more sense to me now. In terms of the code review, I found that stackexchange has a code review site, in case anyone else is curious: https://codereview.stackexchange.com It would be hard to post a sscc example since the parts I am curious about reference other class variables that would be unclear out of context, I think. Much appreciated... On Fri, Aug 1, 2014 at 4:38 AM, Ben Finney wrote: > Peter Otten <__pete...@web.de> writes: > >> C Smith wrote: >> >> > Nice, these are useful tools. I have been building something with >> > just basic stuff and avoiding learning any libraries. If I wanted to >> > get some insight on a larger program that is about 1000 lines, would >> > that be doable here? >> >> In general we prefer concrete questions and smaller chunks of code. >> With 1000 lines you get fewer people to even take a look. > > Right. When attrmpting to learn, keep the examples simple. This will > make it easier to focus on the essential points, and also minimise whole > categories of error. > > To get feedback on some code, make it a Short, Self-Contained, > Compilable Example http://sscce.org/>. This means we will be able > to read the code quickly, run it ourselves, and better see what its > purpose is. > >> You might still try and post a link to the code together with a few >> questions here... > > Not really advised. If the code is too long to discuss in context here, > much of the point is lost; we prefer discussions to have the code inline > so the public archives contain the code too. That's an important reason > to keep it short and self-contained. > > -- > \ “I bought some batteries, but they weren't included; so I had | > `\to buy them again.” —Steven Wright | > _o__) | > Ben Finney > > ___ > Tutor maillist - Tutor@python.org > To unsubscribe or change subscription options: > https://mail.python.org/mailman/listinfo/tutor ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] capturing errors/exceptions..
Clarification. The test py app is being invoked via a system function from a separate app, and not stacktrace gets created. All I have is in the /var/log/messages, an indication that the pyTest app generated an error.. This is noted by the abrtd process, but I have no other data to go on.. Which is why I'm interested in implementing some basic "capture/display" all/any error approach to get a feel for what's happening.. On Fri, Aug 1, 2014 at 10:54 AM, Steven D'Aprano wrote: > On Fri, Aug 01, 2014 at 10:14:38AM -0400, bruce wrote: >> Hi. >> >> Really basic question!! >> >> Got a chunk of some test python, trying to figure out a quick/easy way >> to capture all/any errors/exceptions that get thrown.. > > Why do you want to do that? The answer to your question will depend on > what you expect to do with the exception once you've caught it, and the > answer might very well be "don't do that". > > >> For the test process, I need to "ensure" that I capture any/all >> potential errors.. > > Hmmm. I don't quite see the reason for this. > > If you're running by hand, manually, surely you want to see the > exceptions so that you can fix them? If there's an exception, what do > you expect to do next? > > If you're using the unittest module, it already captures the exceptions > for you, no need to re-invent the wheel. > > >> -Could/Should I wrap the entire func in a try/catch when I call the >> function from the parent process? > > You mean something like this? > > try: > mymodule.function_being_test(x, y, z) > except Exception: > do_something_with_exception() > > > Sure. Sounds reasonable, if you have something reasonable to do once > you've captured the exception. > > >> -Should I have separate try/catch blocks within the function? > > No. That means that the function is constrained by the testing regime. > > >> -The test py app is being run from the CLI, is there a py command line >> attribute that auto captures all errors? > > No. How would such a thing work? In general, once an exception occurs, > you get a cascade of irrelevant errors: > > n = lne(some_data) # Oops I meant len > m = 2*n + 1 # oops, this fails because n doesn't exist > value = something[m] # now this fails because m doesn't exist > ... > > Automatically recovering from an exception and continuing is not > practical, hence Python halts after an exception unless you take steps > to handle it yourself. > > > > -- > Steven > ___ > Tutor maillist - Tutor@python.org > To unsubscribe or change subscription options: > https://mail.python.org/mailman/listinfo/tutor ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Using subprocess on a series of files with spaces
-- On Fri, Aug 1, 2014 12:35 AM CEST Steven D'Aprano wrote: >You may have already have solved your problem, unfortunately my >emails are coming in slowly and out of order, but I have a suggestion: > >On Thu, Jul 31, 2014 at 03:53:48PM -0400, C Smith wrote: >> I am on OSX, which needs to escape spaces in filenames with a backslash. > >Same as any other Unix, or Linux, or, indeed, Windows. > >> There are multiple files within one directory that all have the same >> structure, one or more characters with zero or more spaces in the >> filename, like this: >> 3 Song Title XYZ.flac. >> I want to use Python to call ffmpeg to convert each file to an .mp3. >> So far this is what I was trying to use: >> import os, subprocess >> track = 1 >> for filename in os.listdir('myDir'): >> subprocess.call(['ffmpeg', '-i', filename, str(track)+'.mp3']) >> track += 1 > >I believe that your problem is *not* the spaces, but that you're passing >just the filename and not the directory. subprocess will escape the >spaces for you. Also, let Python count the track number for you. Try >this: > > >directory = '/path/to/the/directory' >for track, filename in enumerate(os.listdir(directory), 1): >pathname = os.path.join(directory, filename) >subprocess.call(['ffmpeg', '-i', filename, str(track)+'.mp3']) Won't that write the mp3 to the current working dir? (Is that the dir where the .py lives? Or even the Python bin dir? Perhaps the cwd parameter of call() will be good? ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Using subprocess on a series of files with spaces
>Won't that write the mp3 to the current working dir? (Is that the dir where >the .py lives? Or even the Python bin dir? Perhaps >the cwd parameter of >call() will be good? Yeah, it just wrote the mp3's to my desktop, where I had the .py script. But that was fine for my purposes. Just for curiosity's sake, would you put cwd outside the list and inside the parens of the subprocess.call()? On Fri, Aug 1, 2014 at 4:23 PM, Albert-Jan Roskam wrote: > > > > -- > On Fri, Aug 1, 2014 12:35 AM CEST Steven D'Aprano wrote: > >>You may have already have solved your problem, unfortunately my >>emails are coming in slowly and out of order, but I have a suggestion: >> >>On Thu, Jul 31, 2014 at 03:53:48PM -0400, C Smith wrote: >>> I am on OSX, which needs to escape spaces in filenames with a backslash. >> >>Same as any other Unix, or Linux, or, indeed, Windows. >> >>> There are multiple files within one directory that all have the same >>> structure, one or more characters with zero or more spaces in the >>> filename, like this: >>> 3 Song Title XYZ.flac. >>> I want to use Python to call ffmpeg to convert each file to an .mp3. >>> So far this is what I was trying to use: >>> import os, subprocess >>> track = 1 >>> for filename in os.listdir('myDir'): >>> subprocess.call(['ffmpeg', '-i', filename, str(track)+'.mp3']) >>> track += 1 >> >>I believe that your problem is *not* the spaces, but that you're passing >>just the filename and not the directory. subprocess will escape the >>spaces for you. Also, let Python count the track number for you. Try >>this: >> >> >>directory = '/path/to/the/directory' >>for track, filename in enumerate(os.listdir(directory), 1): >>pathname = os.path.join(directory, filename) >>subprocess.call(['ffmpeg', '-i', filename, str(track)+'.mp3']) > > Won't that write the mp3 to the current working dir? (Is that the dir where > the .py lives? Or even the Python bin dir? Perhaps the cwd parameter of > call() will be good? > ___ > Tutor maillist - Tutor@python.org > To unsubscribe or change subscription options: > https://mail.python.org/mailman/listinfo/tutor ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Python functions are first-class citizens
On 01/08/14 09:33, Ben Finney wrote: I'm being a stickler on this point because “iterate” implies something quite specific in Python, and this behaviour is not implied by the purpose of ‘max’. Instead, think only “finds the largest item in the collection”. Nope, think the largest in an iterator. The docs say iterator not collection. The max function works with generators which are not collections. Here is an example: >>> def mycount(first,limit): ...n=first ...while n < limit: ... yield n ... n += 1 ... >>> for x in mycount(1,5): ...print x ... 1 2 3 4 >>> max(mycount(2,5)) 4 >>> You don't need a collection to call max() though; I would prefer instead that it says “collection”, because whether the collection is iterable shouldn't matter. But the docs say it does matter. The specification of max() is what the docs say, and they say it should be an iterable. I don't know what happens if you pass a non-iterable collection but the docs do say it should be iterable and assuming that it might work with a non-iterable is the mistake... -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.flickr.com/photos/alangauldphotos ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor