NULLARGUMENT = ()
def someFunctionOrMethod (argument = NULLARGUMENT ):
if argument is NULLARGUMENT:
doSomething()
else:
doSomethingElse()
That is, I was attempting to distinguish between a call where argument is
passed a NULL tuple and a call where argument is passed nothing at all.
When I was working on unit tests for my current piece of code, however, I
discovered that this no longer works (Python 1.5.2). No idea for how long
it hasn't worked. Now, of course, I could have used:
class NULL: pass
NULLARGUMENT = NULL() # a particular instance
or
NULLARGUMENT = NULL # use the class itself
or
NULLARGUMENT = []
or I could've used an approach where I used *arguments and **namedarguments
to determine whether the argument was really passed. There are all sorts of
other ways to do this. Apparently optimisation has come to the tuples of
the world, so using tuple identities is now a no-no.
All those who have used null-tuple identities should now go and fix their
code.
Mike
__________________________________
Mike C. Fletcher
Designer, VR Plumber
http://members.home.com/mcfletch
This will not actually work for the purpose though. The idea is to
distinguish between whether a parameter was passed, or whether the default
parameter is being used. Note: I've never tried this myself ...
If you have a default of None, it is impossible to determine this if the
user passes None - because it will be the same instance of None in almost
all cases.
Obviously, previously all tuples were distinct objects, even if they
compared the same. Thus this technique worked. However, some tuples are now
obviously being interned (the empty tuple for example), meaning that if a
user passes an empty tuple you can no longer distinguish the two.
# Will never work
def func (p=None):
if p is None:
print 'Default parameter'
else:
print 'Parameter passed'
func() # prints 'Default parameter'
func(None) # prints 'Default parameter'
# Will work if empty tuple is not interned
__nullArgument = ()
def func (p=__nullArgument):
if p is __nullArgument:
print 'Default parameter'
else:
print 'Parameter passed'
func() # prints 'Default parameter'
func(()) # we want it to print 'Parameter passed',
# will probably print 'Default parameter'
# Should always work
class nullArgument:
""""""
__nullArgument = nullArgument()
def func (p=__nullArgument):
if p is __nullArgument:
print 'Default parameter'
else:
print 'Parameter passed'
func() # prints 'Default parameter'
func(nullArgument()) # prints 'Parameter passed'
# There is a better way to do this one though ...
class __nullArgument:
""""""
__nullArgument = __nullArgument()
def func (p=__nullArgument):
if p is __nullArgument:
print 'Default parameter'
else:
print 'Parameter passed'
# Now *can't* pass an instance of the class, so it will never compare true
Tim Delaney
The convention is to use 'None' for this purpose. 'None' never changes, so
'argument is None' will work correctly for you.
-Steve
--
Steve Purcell, Pythangelist
Get testing at http://pyunit.sourceforge.net/
Any opinions expressed herein are my own and not necessarily those of Yahoo
NULL = (1,) # why doesn't () work? Get with it Guido ;)
As for cheating... no, actually, I didn't feel guilty, I was thinking of ()
and [] as being calls to constructors which returned shiny new tuple and/or
list objects (with the contents being arguments to those constructors).
I've learned a lot since then; now I know that the list gnomes and the tuple
fairies sneak in and replace the bracket characters with billows of cotton
candy. Problems arise when the cotton candy is soaked by over optimisation
by the evil language wizards, though I discovered that the resulting
solution is quite tasty when carbonated.
In some weird way, I like the is statement. It appears in thousands of
places throughout my code. I check object identity far more often than
object equivalence, as many of my libraries, in order to do a decent
equality check might have to do a recursive search through thousands of
nodes (and since they can have references to their parents, the equality
becomes quite ugly). Still, carbonation makes it all quite palatable.
Just because something is explicitly forbidden, goes against all laws of
nature, offends half the population, destroys one's life and family, and
casts one into the deepest pits of Tartarus doesn't necessarily mean that
thing should be avoided...
Or so I tell myself...
Mike
PS: Pointing out that it's in a document with the official disclaimer: "for
language lawyers" , is like pointing out ''There's no point in acting all
surprised about it. All the planning charts and demolition orders have been
on display in your local planning department on Alpha Centauri for fifty of
your Earth years, so you've had plenty of time to lodge any formal complaint
and it's far too late to start making a fuss about it now.'' ;)
-----Original Message-----
From: Tim Peters [mailto:tim...@home.com]
Sent: Wednesday, April 18, 2001 03:51
To: Python List (E-mail)
Subject: RE: Idiom gone, or did it really ever exist? () is ()
...
It has never worked by design. It stopped working by accident when Guido
added empty-tuple caching in revision 2.9 of tupleobject.c. He did that in
October of 1993. Have you been in a time warp <wink>?
Any code relying on unique object identity for literals of any object of any
immutable type is simply wrong. The language doesn't guarantee anything
here, and the implementation can & does vary across releases, or even
bugfixes. The Reference Manual has always said (section "Objects, values
and
types"):
...
I don't know what accounts for this. Do users not understand how object
identity works in Python, or are they so fanatically devoted to tricks that
they're willing to chance it despite knowing it isn't safe? 'Fess up, Mike:
my bet is that when you *started* using this trick, you knew you were
cheating.
...
More generally, people using "is" without knowing what they're doing should
simply stop using it, tuples or not. How to tell if you're one of them: if
when you use "is", you feel a twinge of pride in being clever <0.5 wink>.
Safe (intended, documented and supported) uses for "is" are dull as dog
food.
...
> You want this kind of construct when creating "generic services" that
> can process any object type (including None), so need to be able to
> determine whether the object passed is, in fact, the value None, or
> merely the absence of a value.
>
>
So why not use the portable and safe way of finding out whether your
function was called with a particular argument or not?
def foo(**kw):
validargs = { 'bar': None }
validargs.update(kw)
assert len(validargs)==1
if kw.has_key('bar'):
print "Have bar"
else:
print "No bar"
--
Duncan Booth
dun...@dales.rmplc.co.uk
int month(char *p){return(124864/((p[0]+p[1]-p[2]&0x1f)+1)%12)["\5\x8\3"
"\6\7\xb\1\x9\xa\2\0\4"];} // Who said my code was obscure?
Why not
_NULL = []
and then
def x(y=_NULL):
if y is _NULL: print "no argument"
i.e., your original trick, but with a _mutable_ object. This
way it should keep working forever, I believe.
Alex
class NULLARGUMENT: pass
Then I use the class as the default value for is-checking.
Which I'm told is evil :) .
Mike
-----Original Message-----
From: Alex Martelli [mailto:ale...@yahoo.com]
Sent: Wednesday, April 18, 2001 07:01
To: pytho...@python.org
Subject: Re: Idiom gone, or did it really ever exist? () is ()
...
Why not
_NULL = []
and then
def x(y=_NULL):
if y is _NULL: print "no argument"
i.e., your original trick, but with a _mutable_ object. This
way it should keep working forever, I believe.
...
Umm, I might be missing something but I think the following does that
:
def my_func( an_arg ) :
do_something( an_arg )
If it is called with the absence of a value, an error will be raised
by the interpreter, otherwise it is passed an object (possibly None).
-D
>Over the years, I've occasionally used this idiom:
>
>NULLARGUMENT = ()
>
>def someFunctionOrMethod (argument = NULLARGUMENT ):
> if argument is NULLARGUMENT:
> doSomething()
> else:
> doSomethingElse()
>
>That is, I was attempting to distinguish between a call where argument is
>passed a NULL tuple and a call where argument is passed nothing at all.
>When I was working on unit tests for my current piece of code, however, I
>discovered that this no longer works (Python 1.5.2).
I like your idiom and often use it, but you have a minor bug. You say
you wish to distinguish between two cases:
- passing an empty tuple
- passing no argument at all
yet your default value for "argument" *is* an empty tuple, so your code
cannot do the job. If you really want to do this job, pick any other
default value, such as None or "".
A good choice of default depends on what values you expect. An example:
in some of my GUI coding I want to distinguish between three cases:
- use a user-specified label
- use a default label
- no label
In that case I tend to code things as follows:
def myFunc(label=None):
"""A demonstration of default arguments
Inputs:
- label: if omitted, a default is supplied; if "" then no label
"""
if label:
print "label =:", label
elif label is None:
print "default label"
else:
print "no label"
-- Russell
def fun(*args):
if args == ((),):
print 'We passed an empty tuple'
elif args == ():
print 'We didn't pass any arguments'
else:
print 'We passed the following arguments:' % args
--Stephen
(replace 'NOSPAM' with 'seraph' to respond in email)
"Mike C. Fletcher" <mcfl...@home.com> wrote in message
news:mailman.987608307...@python.org...
-----= Posted via Newsfeeds.Com, Uncensored Usenet News =-----
http://www.newsfeeds.com - The #1 Newsgroup Service in the World!
-----== Over 80,000 Newsgroups - 16 Different Servers! =-----
That is another immutable object. CPython doesn't cache those
objects yet but its better to use:
NULL = []
instead. Or:
class NULL:
pass
if you think that's more clear.
Neil
His function should also work when no argument was given. Except it should
do something special then.
--
Remco Gerlich
When I first faced this problem, I started typing in code that was
equivalent to yours, until it occurred to me that there is no reason
to instantiate the class--the class itself serves as a fine default
argument. In other words,
class __nullArgument:
pass # Isn't this what pass is for?
def func (p=__nullArgument):
if p is __nullArgument:
print 'Default parameter'
else:
print 'Parameter passed'
Cheers,
Michael
--
Michael Haggerty
mha...@alum.mit.edu