This recipe presents an ideom for simplified accessors, that combines typical getter and setter functionality of an attribute into a single overloaded method, that instead of getATTRIBUTE and setATTRIBUTE can now just be called ATTRIBUTE. When called without arguments it acts as a getter and retrieves the attribute's value. When called with arguments, the attribute is set to this value.
Uses a neat trick of an exclusive unique value in default arguments.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | #!/usr/bin/env python
__version__ = "1.0"
"""OverloadedAccessors.py
This recipe presents an ideom for simplified accessors, that combines
typical getter and setter functionality of an attribute into a single
overloaded method, that instead of getATTRIBUTE and setATTRIBUTE can
now just be called ATTRIBUTE. When called without arguments it acts as
a getter and retrieves the attribute's value. When called with
arguments, the attribute is set to this value.
Keywords: accessor, getter, setter, overload, read/only attribute,
unique value, default argument
"""
omitted=[] # omitted contains an exclusive unique value
class Person:
def __init__(self, givenName, name):
self._givenName=givenName
self._name=name
# read write accessor
def givenName(self, value=omitted):
if value is not omitted: # check for exclusive unique value
self._givenName=value
return self._givenName
# read only accessor
def name(self):
return self._name
print ("The special unique value has the id %s. No other Python object is "
"identical (unsing the 'is' operator) to it.\n" % id(omitted))
p=Person('Ulrich', 'Hoffmann')
print p.givenName(), p.name() # Read attributes through accessors
print p.givenName('Ulrich Ernst') # Write attribute through accessor
print p.givenName(), p.name()
try:
print p.name("") # Read/only accessor
except TypeError:
print "I cannot set the value of 'name' in object %s. This is expected." % p
|
This recipe presents an ideom for simplified accessors, that combines typical getter and setter functionality of an attribute into a single overloaded method, that instead of getATTRIBUTE and setATTRIBUTE can now just be called ATTRIBUTE. When called without arguments it acts as a getter and retrieves the attribute's value. When called with arguments, the attribute is set to this value.
Overloading the accessor is done with a neat trick. The global
constant (well Python variable) omitted
is defined to contain an
exclusive unique object (An empty list is used in the example, but any
exclusive object would do). This is used as the default value in the
accessors parameter list. When checked against it leads to the nice
phrase 'if value is not omitted'. If so, a value is given and this
value will be written to the attriute. In any case the (new) attribute
value is returned, so the accessor acts as getter when no argument is
given.
The attribute thus can be set to all values except the exclusive
unique value in omitted
. This is not a problem as this value was
chosen to be exclusively used for this purpose.
Defining getters and setters is a standard object-oriented technique. They are discussed in many text books and certainly in comp.lang.python. Combining them is a common technique that I first saw in Lisp programs.
Default parameters are a standard technique. Typically None (instead
of omitted
) is used to control missing arguments, but this excludes
None to be used as a proper default value. Our aproach just excludes the
exclusive unique value in omitted
, which is no loss whatsoever.
There is the pitfall with mutable default arguments in Python, that the default expressions are evaluated at function definition time and not at invocation time. For details see for example "Learning Python", Chapter 4, Section "Defaults and Mutable Objects".
The use of the exclusive unique value for default parameters is probably unique (no pun intended), i.e. I haven't seen it elsewhere.
Keywords: accessor, getter, setter, overload, read/only attribute, unique value, default argument
ideom - idiom. This certainly has to be written idiom instead of ideom. [I was about to look it up in the dictionary but submitted before I got the result :-(]
Sorry for my bad english.
This is what I mean:
Uniques are evil. I like the idea, although in practice I can't think of a value that's unique in every case. This could sneak in some really creepy bugs.
There is another way to test the number of arguments fed to a function.