Re: [Tutor] design advice for function
Christopher Spears said unto the world upon 2005-12-18 01:30: > I got my function to work! It takes arguments and > adds them: Hi Christopher, great! > def adder(**args): > argsList = args.values() > sum = argsList[0] > for x in argsList[1:]: > sum = sum + x > return sum > > print adder() > print "---" > print adder(a=5) > print "---" > print adder(a=5,b=6) > print "---" > print adder(a=5,b=6,c=7) > print "---" > print adder(ugly=7, good=6, bad=5) > print "---" > > However, if I run the above code. I get an error: > > Traceback (most recent call last): > File "C:\Documents and Settings\Christopher > Spears\My > Documents\programming\PythonScripts\Part4\Ex04\adder.py", > line 8, in -toplevel- > print adder() > File "C:\Documents and Settings\Christopher > Spears\My > Documents\programming\PythonScripts\Part4\Ex04\adder.py", > line 3, in adder > sum = argsList[0] > IndexError: list index out of range > > This is caused by the line: print adder(). Obviously > if adder() doesn't receive any arguments, it can't > build the lists resulting in an IndexError. Right. You are also going to have a like problem with the next chunk of you function: for x in argsList[1:]: sum = sum + x (If you fix the adder() problem alone, you will still have a adder(one_arg) problem.) > What is > the best way to solve this? Should I write some > syntax into the function to check for arguments? > Should I just write a seperate function to check for arguments? Well, what you like adder() to do? It is not uncommon for operations of a sequence to have a separate clause for the special case of the empty sequence. So, you could do: if not argsList: return what_Christopher_wants If you do that, can you think of a way to get around the adder(one_arg) problem? Hint: do you really need to treat the first element of argsList as a special case? Have a think, and if you get stuck, post again. Best, Brian vdB ___ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] design advice for function
Christopher Spears wrote: > I got my function to work! It takes arguments and > adds them: > > def adder(**args): > argsList = args.values() > sum = argsList[0] > for x in argsList[1:]: > sum = sum + x > return sum > > print adder() > > However, if I run the above code. I get an error: > > Traceback (most recent call last): > sum = argsList[0] > IndexError: list index out of range > > This is caused by the line: print adder(). Obviously > if adder() doesn't receive any arguments, it can't > build the lists resulting in an IndexError. What is > the best way to solve this? Should I write some > syntax into the function to check for arguments? > Should I just write a seperate function to check for arguments? Actually adder is still receiving an argument, it is an empty dictionary: >>> def adder(**args): ... print args ... >>> adder() {} If you iterate the whole items() list then Python will do the right thing (i.e. nothing) when the list is empty. Can you think of another way to initialize sum that lets you iterate the whole list instead of slicing off the first element? A couple of notes: - I'm not sure why you are passing keyword arguments, do you know that there is a way to pass a variable list of arguments to a function? Use a single * in the parameter list and unnamed arguments at the point of call. The argument list is passed as a tuple: >>> def adder(*args): ... print args ... >>> adder() () >>> adder(1, 2, 3) (1, 2, 3) Of course if you want the keyword style of argument passing then keep doing what you are doing. - The name of the keyword parameter is conventionally something like kwds or kwargs. 'args' is usually used for a variable argument list as in my second example. Your code may be easier for others to understand if you use this convention. (At least I was thrown for a moment by **args and read it as *args.) Kent ___ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] design advice for function
> def adder(**args): >argsList = args.values() >sum = argsList[0] >for x in argsList[1:]: >sum = sum + x >return sum > line 3, in adder >sum = argsList[0] > IndexError: list index out of range > > This is caused by the line: print adder(). Obviously > if adder() doesn't receive any arguments, it can't > build the lists resulting in an IndexError. What is > the best way to solve this? Should I write some > syntax into the function to check for arguments? The Pythonic way is to use exceptions. You can either handle the exception inside the function or outside: def adder(**args): try: # your code hee except IndexError: return 0 # or some other default, perhaps even None?! OR def adder(**args): try: # your code hee except IndexError: raise try: print adder() print addre(a=1) # etc... except IndexError: print 'oops, no arguments to adder' In this case I'd probably use the first approach (with None as default), but its up to you... Alan G ___ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Accessing next and previous items during iteration
Ed Singleton wrote: > Is it possible to access the next and previous items during an iteration? This just came up on c.l.python. Bengt Richter has a nice generator-based solution. http://groups.google.com/group/comp.lang.python/browse_thread/thread/2e4533f108fbf172/90d87c91dac844d3?hl=en#90d87c91dac844d3 Kent ___ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] design advice for function
On Sun, 18 Dec 2005, Alan Gauld wrote: > > def adder(**args): > >argsList = args.values() > >sum = argsList[0] > >for x in argsList[1:]: > >sum = sum + x > >return sum > > > line 3, in adder > >sum = argsList[0] > > IndexError: list index out of range > > > > This is caused by the line: print adder(). Obviously if adder() > > doesn't receive any arguments, it can't build the lists resulting in > > an IndexError. What is the best way to solve this? Should I write > > some syntax into the function to check for arguments? > > The Pythonic way is to use exceptions. Hi Alan, I disagree for this particular situation: adder() can be written so it doesn't raise an exception on empty input. Brian gave a hint about this when he asked: what happens if we try to sum up an empty sequence? Without looking at the body of the function, what value do we want to get from the call to "adder()" with no arguments? Once we know this, then we can go toward defining our function to do what we want. ___ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] design advice for function
> > This is caused by the line: print adder(). Obviously > > if adder() doesn't receive any arguments, it can't > > build the lists resulting in an IndexError. > > Right. Hello! Just wanted to clarify the situation: argsList ends up being the empty list, which is a perfectly good value: ## >>> d = {} >>> l = d.values() >>> l [] ## So lists are being built perfectly ok. The issue is that the operations that we do on them later should account for the possibility that the lists are empty. One thing about the empty list, in particular, is this: because it has no elements, it's an invalid operation to try to get the first element of an empty list: ## >>> l[0] Traceback (most recent call last): File "", line 1, in ? IndexError: list index out of range ## Programmers will often call say something like "Don't forget the null/empty case!", which is what this is. *grin* Best of wishes! ___ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] design advice for function
>> > line 3, in adder >> >sum = argsList[0] >> > IndexError: list index out of range >> > >> > an IndexError. What is the best way to solve this? Should I write >> > some syntax into the function to check for arguments? >> >> The Pythonic way is to use exceptions. > > I disagree for this particular situation: adder() can be written so it > doesn't raise an exception on empty input. Brian gave a hint about this > when he asked: what happens if we try to sum up an empty sequence? That's why I said I'd use the exception internally but return None from within the exception handler. I just think that catching the exception is the natural way to process the case of an empty input. Certainly cleaner than putting special processing in the main code body. (The real problem here is to figure out what exactly an adder should do when given nothing to add...) But maybe that's just me... Alan G. ___ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor
[Tutor] Name tables questions
Hello, I have a few theoric questions regarding name tables. I wish to better understand a few things about this aspect of Python, in particular how module names and the import statements fit into the picture of name tables. - First of all, I understand each scope has its "local" name table, containing all the names defined in this scope, no matter the origin of the name. So, if you import a module in a scope, its name is added to the local scope name table, correct? - When you import a module, I understand the module name is appended to Python dictionary of imported modules. I can see the name of the module if I print out the sys.modules attribute. If the module name is also added to the local scope name table, it does mean that the module is added in two tables: the local scope name table and the imported modules table. Is that correct? - I *think* I have read in Learning Python (sorry I don't have the book near me) that during execution, when Python doesn't find a name in the current scope name table, then it will look up every encompassing name table one after another, until it can find it, and if it can't, will raise an error. If I remember correctly about my reading, this lookup into an encompassing name table has a performance cost. The author suggests that, without regard to the practical considerations, it would not be such a bad idea to pass down all possible names to functions and encapsulated functions so name lookup into other tables could be avoided. Now, let say I would do something like that, and be zealous at that, to the point where I would write import statements for the same modules in every possible function to define the module name there. Since the module name is already in the module names dictionary but not in the global name table, would there be any advantage, or disadvantage in doing so? Thanks in advance Bernard ___ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor