|
2011-07-14 Ramblings on handling optional arguments in Python
This gives me a platform to spring off from. Python has the same 'problem' as Ruby here, ultimately because their language designers have picked the same solutions to the problem of optional arguments for functions. Roughly speaking, I can think of three ways of handling optional arguments in a language: declare them explicitly, use default values, or explicitly handle at least some of the argument list yourself. A language that lets you explicitly declare optional argument can also support an explicit and direct check to see which optional arguments were supplied. I believe that Lisps have historically supported this approach. However, this is extra syntax and an extra language feature; both Python and Ruby have opted not to have this and to only support optional function arguments indirectly, through either of the other two approaches. Handling part of the argument list yourself leaves you to decode it into actual variables (present and absent). This is annoying, so most people wind up using arguments with default values; essentially this pre-decodes the optional portion of the argument list for you. But it does leave you with a problem, one that Lisp people note explicitly in their documentation: since you're using the argument's default value as a signal that the caller didn't supply it, you need a way of distinguishing between the argument not being supplied and your caller supplying a value that happens to also be your 'argument was not supplied' default value. This is a specific instance of a general situation where you need a
sentinel value that can be distinguished from all valid values. Since
Python is dynamically typed, often the simplest way to get such a value
is to create one yourself and the simplest way to do that is just to
create a new instance of no_arg = object() (You might as well use You don't need to create your own new sentinel value if you can come
up with a convenient existing value that no caller will ever supply
(perhaps because it's invalid). (The problem with If you use this idiom a lot, it might be worthwhile to create a function so that you can use a clear name: def unique_value(): return object() no_arg = unique_value() (Trivia: there is a tiny reason to make this a function instead
of a subclass of These sentinel values are not completely ideal; for example, they are not self-documenting if you display them during debugging. But doing better requires more verbosity and repetition, at least in Python. (This is one of the cases where it would be nice to have a real built in and fully supported symbol type, and yes syntactic sugar does matter.) (This issue came up in passing before in DefaultArgumentsTrick.) Sidebar: on unique values in PythonWhen I say 'unique value', I mean 'some object that we can reliably
distinguish from all other objects in the Python universe'. Note that
certain sorts of built in values (and thus objects, because in Python
everything is an object) that you might think are unique are not in
fact unique in CPython, because the CPython interpreter plays tricks
behind your back. A full discussion of these tricks is an entry in and
of itself, but the short version is that you're safe from them if you
use a mutable type. Instances of (4 comments.)
python/OptionalArgumentsIssue written at 02:11:47; Add Comment
|
These are my WanderingThoughts GettingAround This is part of CSpace, and is written by ChrisSiebenmann. * * * Atom feeds are available; see the bottom of most pages. Categories: links, linux, programming, python, snark, solaris, spam, sysadmin, tech, unix, web |