A way to allow functions with 0, 1, and -1 arguments! For those times you want to differentiate a no value argument from a non-value argument.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
class Thing(object): """A thing, does stuff.""" def __init__(self): self.special = "My special value!" def process(self, default=True): """Accept any argument with no special processing (except True).""" if default is True: # Notice I'm checking identity, not truth or equality default = self.special elif not default: # Optional check for False values print "Non-value given!" print default if __name__ == "__main__": t = Thing() t.process() # Prints t's special value t.process("something") # Prints 'something' t.process(None) # Prints the False value warning
Say you have a method of some object, and as the default argument you want it to use an instance variable. Suppose also that this argument can also be something else, or even None (to indicate no action should be taken). How do you make a default argument that allows all these at once?
In my case I am passing messages using queues. I have a method that wraps all my data in a tuple, and puts it on a queue. The last part of the message is another queue for receiving return messages. By default it uses the class instance's input queue, but you could also get results into a special separate queue, or you could not care about results and just pass None.
I would like to just say def foo(self, result=self.in_queue): but default args are bound at definition, and there exists neither a self nor an in_queue when the method is defined. The other trick I would use is def foo(self, result=None): then if not result set result = self.in_queue. But I wanted to leave the possibility of passing an empty value to disable returns.
I guess you could use the result=None trick and just have some other special value (like False?) signal that no results are required. I think it is nicer (and more explicit) to handle the default this way though, rather than forcing the caller to use some special value (secret handshake).
Building on your idea, instead of using True for your token, create a global- or class- variable and set it to something mutable like a list. For example:
This allows you to True as a valid value and additionally (by using a well-named variable) is "self-documenting".
The usual idiom is like Chris Phillips described it, but with
USE_DEFAULT = object()to make clear it is not to be used as an actual list.
Yeah, basically any unique identity will work.
As for my intended use of this trick: I RTFM and multiprocessing doesn't let you pass queue pointers across processes... duh. Not too hard to re-factor to a GUID though!