Welcome, guest | Sign In | My Account | Store | Cart

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.

Python, 52 lines
 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

2 comments

Ulrich Hoffmann (author) 20 years, 8 months ago  # | flag

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:

\Id"i*om\, n. [F. idiome, L. idioma, fr. Gr. ?, fr. ? to
make a person's own, to make proper or peculiar; prob. akin
to the reflexive pronoun ?, ?, ?, and to ?, ?, one's own, L.
suus, and to E. so.]

1. The syntactical or structural form peculiar to any
   language; the genius or cast of a language.

2. An expression conforming or appropriate to the peculiar
   structural form of a language; in extend use, an
   expression sanctioned by usage, having a sense peculiar to
   itself and not agreeing with the logical sense of its
   structural form; also, the phrase forms peculiar to a
   particular author
W.J. van der Laan 20 years, 5 months ago  # | flag

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.

def function(*args):
  if args:
    # args is not the empty tuple
    something(args[0])
  else:
    # args is the empty tuple
    return args[0]
Created by Ulrich Hoffmann on Sun, 17 Aug 2003 (PSF)
Python recipes (4591)
Ulrich Hoffmann's recipes (2)

Required Modules

  • (none specified)

Other Information and Tasks