1 """null.py
2
3 This is a sample implementation of the 'Null Object' design pattern.
4
5 Roughly, the goal with Null objects is to provide an 'intelligent'
6 replacement for the often used primitive data type None in Python or
7 Null (or Null pointers) in other languages. These are used for many
8 purposes including the important case where one member of some group
9 of otherwise similar elements is special for whatever reason. Most
10 often this results in conditional statements to distinguish between
11 ordinary elements and the primitive Null value.
12
13 Among the advantages of using Null objects are the following:
14
15 - Superfluous conditional statements can be avoided
16 by providing a first class object alternative for
17 the primitive value None.
18
19 - Code readability is improved.
20
21 - Null objects can act as a placeholder for objects
22 with behaviour that is not yet implemented.
23
24 - Null objects can be replaced for any other class.
25
26 - Null objects are very predictable at what they do.
27
28 To cope with the disadvantage of creating large numbers of passive
29 objects that do nothing but occupy memory space Null objects are
30 often combined with the Singleton pattern.
31
32 For more information use any internet search engine and look for
33 combinations of these words: Null, object, design and pattern.
34
35 Dinu C. Gherman,
36 August 2001
37
38 For modifications see CVS changelog below.
39
40 Karsten Hilbert
41 July 2004
42 """
43
44
45 __version__ = "$Revision: 1.6 $"
46 __author__ = "Dinu C. Gherman"
47 __license__ = "GPL v2 or later (details at http://www.gnu.org)"
48
49
51 """A class for implementing Null objects.
52
53 This class ignores all parameters passed when constructing or
54 calling instances and traps all attribute and method requests.
55 Instances of it always (and reliably) do 'nothing'.
56
57 The code might benefit from implementing some further special
58 Python methods depending on the context in which its instances
59 are used. Especially when comparing and coercing Null objects
60 the respective methods' implementation will depend very much
61 on the environment and, hence, these special methods are not
62 provided here.
63 """
64 _warn = 0
65
66
67
69 "Ignore parameters."
70 try:
71 cNull._warn = kwargs['warn']
72 except KeyError:
73 pass
74 return None
75
76
77
79 "Ignore method calls."
80 if cNull._warn:
81 print "cNull.__call__()"
82 return self
83
84
85
87 "Ignore attribute requests."
88 if cNull._warn:
89 print "cNull.__getattr__()"
90 return self
91
93 "Ignore attribute setting."
94 if cNull._warn:
95 print "cNull.__setattr__()"
96 return self
97
99 "Ignore deleting attributes."
100 if cNull._warn:
101 print "cNull.__delattr__()"
102 return self
103
104
105
107 "Return a string representation."
108 if cNull._warn:
109 print "cNull.__repr__()"
110 return "<cNull instance @ %s>" % id(self)
111
113 "Convert to a string and return it."
114 if cNull._warn:
115 print "cNull.__str__()"
116 return "cNull instance"
117
119 if cNull._warn:
120 print "cNull.__nonzero__()"
121 return 0
122
124 if cNull._warn:
125 print "cNull.__len__()"
126 return 0
127
128
130 "Perform some decent tests, or rather: demos."
131
132
133
134 n = cNull()
135 n = cNull('value')
136 n = cNull('value', param='value', warn=1)
137
138 n()
139 n('value')
140 n('value', param='value')
141
142
143
144 n.attr1
145 n.attr1.attr2
146 n.method1()
147 n.method1().method2()
148 n.method('value')
149 n.method(param='value')
150 n.method('value', param='value')
151 n.attr1.method1()
152 n.method1().attr1
153
154 n.attr1 = 'value'
155 n.attr1.attr2 = 'value'
156
157 del n.attr1
158 del n.attr1.attr2.attr3
159
160
161 tmp = '<cNull instance @ %s>' % id(n)
162 assert repr(n) == tmp
163 assert str(n) == 'cNull instance'
164
165
166 if n == 1:
167 print "Null object == 1"
168 else:
169 print "Null object != 1"
170
171 if __name__ == '__main__':
172 test()
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196