Re: [Tutor] design advice for function

2005-12-18 Thread Brian van den Broek
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

2005-12-18 Thread Kent Johnson
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

2005-12-18 Thread Alan Gauld
> 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

2005-12-18 Thread Kent Johnson
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

2005-12-18 Thread Danny Yoo


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

2005-12-18 Thread Danny Yoo
>  > 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

2005-12-18 Thread Alan Gauld
>> > 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

2005-12-18 Thread Bernard Lebel
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