Suggestions for good programming practices?

Bengt Richter bokr at oz.net
Wed Jun 26 02:53:22 CEST 2002


On 25 Jun 2002 17:49:38 -0400, aahz at pythoncraft.com (Aahz) wrote:

>In article <afafee$fc$0 at 216.39.172.122>, Bengt Richter <bokr at oz.net> wrote:
>>
>>Do you recommend using def foo(*args) and testing len(args) instead?
>
>Only if you really want a list of unnamed parameters.  Personally, I
>usually prefer to pass a sequence directly in such cases, to distinguish
>between None (i.e. no list) and the empty list.

Well, I meant using *args to allow detecting actual "no default-overriding
argument passed", in place of x=None. The arg list items (only x here)
don't have to remain unnamed long. E.g.,

 >>> def foo(*args):
 ...     if len(args)==1:
 ...         print "We know we have one non-default arg: %s" % `args[0]`
 ...         x = args[0]
 ...     elif len(args)==0:
 ...         print "We can supply a default arg, even None"
 ...         x = None
 ...     else: raise TypeError,'foo() takes 0 or 1 arguments (%d given)' % len(args)
 ...     print 'Effective arg was: %s' % `x`
 ...
 >>> foo('one arg')
 We know we have one non-default arg: 'one arg'
 Effective arg was: 'one arg'
 >>> foo(None)
 We know we have one non-default arg: None
 Effective arg was: None
 >>> foo()
 We can supply a default arg, even None
 Effective arg was: None
 >>> foo(None,'too many')
 Traceback (most recent call last):
   File "<stdin>", line 1, in ?
   File "<stdin>", line 8, in foo
 TypeError: foo() takes 0 or 1 arguments (2 given)

Hm. It occurs to me that *args also lets you put defaults at the front if you like,
and specify not just min and max number of args. E.g., a textout method could
use current x,y by default or allow override (obviously this example is just
about parameter passing, not graphics output. And no prizes for speed ;-)

 >>> class GX:
 ...     def __init__(self, x, y): self.x, self.y = x,y
 ...     def textout(self, *args):
 ...         if len(args) not in (1,3):
 ...             raise TypeError,"Use textout('string') or textout(x,y,'string') (%d args given)" % len(args)
 ...         if len(args)==1:
 ...             x, y, a = self.x, self.y, args[0]
 ...         else:
 ...             x, y, a = args
 ...         print 'output "%s" at %s,%s' % (a, x, y)
 ...
 >>> g=GX(123, 456)
 >>> g.textout('using curr pos')
 output "using curr pos" at 123,456
 >>> g.textout(333, 444, 'using spec pos')
 output "using spec pos" at 333,444

And accurate arg count validation can be had (ignoring types):
 >>> g.textout()
 Traceback (most recent call last):
   File "<stdin>", line 1, in ?
   File "<stdin>", line 5, in textout
 TypeError: Use textout('string') or textout(x,y,'string') (0 args given)
 >>> g.textout(1,2)
 Traceback (most recent call last):
   File "<stdin>", line 1, in ?
   File "<stdin>", line 5, in textout
 TypeError: Use textout('string') or textout(x,y,'string') (2 args given)
 >>> g.textout(1,2,3,4)
 Traceback (most recent call last):
   File "<stdin>", line 1, in ?
   File "<stdin>", line 5, in textout
 TypeError: Use textout('string') or textout(x,y,'string') (4 args given)

Regards,
Bengt Richter



More information about the Python-list mailing list