0001 # This contains most of the executable examples from Guido's descr 0002 # tutorial, once at 0003 # 0004 # http://www.python.org/2.2/descrintro.html 0005 # 0006 # A few examples left implicit in the writeup were fleshed out, a few were 0007 # skipped due to lack of interest (e.g., faking super() by hand isn't 0008 # of much interest anymore), and a few were fiddled to make the output 0009 # deterministic. 0010 0011 from test.test_support import sortdict 0012 import pprint 0013 0014 class defaultdict(dict): 0015 def __init__(self, default=None): 0016 dict.__init__(self) 0017 self.default = default 0018 0019 def __getitem__(self, key): 0020 try: 0021 return dict.__getitem__(self, key) 0022 except KeyError: 0023 return self.default 0024 0025 def get(self, key, *args): 0026 if not args: 0027 args = (self.default,) 0028 return dict.get(self, key, *args) 0029 0030 def merge(self, other): 0031 for key in other: 0032 if key not in self: 0033 self[key] = other[key] 0034 0035 test_1 = """ 0036 0037 Here's the new type at work: 0038 0039 >>> print defaultdict # show our type 0040 <class 'test.test_descrtut.defaultdict'> 0041 >>> print type(defaultdict) # its metatype 0042 <type 'type'> 0043 >>> a = defaultdict(default=0.0) # create an instance 0044 >>> print a # show the instance 0045 {} 0046 >>> print type(a) # show its type 0047 <class 'test.test_descrtut.defaultdict'> 0048 >>> print a.__class__ # show its class 0049 <class 'test.test_descrtut.defaultdict'> 0050 >>> print type(a) is a.__class__ # its type is its class 0051 True 0052 >>> a[1] = 3.25 # modify the instance 0053 >>> print a # show the new value 0054 {1: 3.25} 0055 >>> print a[1] # show the new item 0056 3.25 0057 >>> print a[0] # a non-existant item 0058 0.0 0059 >>> a.merge({1:100, 2:200}) # use a dict method 0060 >>> print sortdict(a) # show the result 0061 {1: 3.25, 2: 200} 0062 >>> 0063 0064 We can also use the new type in contexts where classic only allows "real" 0065 dictionaries, such as the locals/globals dictionaries for the exec 0066 statement or the built-in function eval(): 0067 0068 >>> def sorted(seq): 0069 ... seq.sort() 0070 ... return seq 0071 >>> print sorted(a.keys()) 0072 [1, 2] 0073 >>> exec "x = 3; print x" in a 0074 3 0075 >>> print sorted(a.keys()) 0076 [1, 2, '__builtins__', 'x'] 0077 >>> print a['x'] 0078 3 0079 >>> 0080 0081 Now I'll show that defaultdict instances have dynamic instance variables, 0082 just like classic classes: 0083 0084 >>> a.default = -1 0085 >>> print a["noway"] 0086 -1 0087 >>> a.default = -1000 0088 >>> print a["noway"] 0089 -1000 0090 >>> 'default' in dir(a) 0091 True 0092 >>> a.x1 = 100 0093 >>> a.x2 = 200 0094 >>> print a.x1 0095 100 0096 >>> d = dir(a) 0097 >>> 'default' in d and 'x1' in d and 'x2' in d 0098 True 0099 >>> print sortdict(a.__dict__) 0100 {'default': -1000, 'x1': 100, 'x2': 200} 0101 >>> 0102 """ 0103 0104 class defaultdict2(dict): 0105 __slots__ = ['default'] 0106 0107 def __init__(self, default=None): 0108 dict.__init__(self) 0109 self.default = default 0110 0111 def __getitem__(self, key): 0112 try: 0113 return dict.__getitem__(self, key) 0114 except KeyError: 0115 return self.default 0116 0117 def get(self, key, *args): 0118 if not args: 0119 args = (self.default,) 0120 return dict.get(self, key, *args) 0121 0122 def merge(self, other): 0123 for key in other: 0124 if key not in self: 0125 self[key] = other[key] 0126 0127 test_2 = """ 0128 0129 The __slots__ declaration takes a list of instance variables, and reserves 0130 space for exactly these in the instance. When __slots__ is used, other 0131 instance variables cannot be assigned to: 0132 0133 >>> a = defaultdict2(default=0.0) 0134 >>> a[1] 0135 0.0 0136 >>> a.default = -1 0137 >>> a[1] 0138 -1 0139 >>> a.x1 = 1 0140 Traceback (most recent call last): 0141 File "<stdin>", line 1, in ? 0142 AttributeError: 'defaultdict2' object has no attribute 'x1' 0143 >>> 0144 0145 """ 0146 0147 test_3 = """ 0148 0149 Introspecting instances of built-in types 0150 0151 For instance of built-in types, x.__class__ is now the same as type(x): 0152 0153 >>> type([]) 0154 <type 'list'> 0155 >>> [].__class__ 0156 <type 'list'> 0157 >>> list 0158 <type 'list'> 0159 >>> isinstance([], list) 0160 True 0161 >>> isinstance([], dict) 0162 False 0163 >>> isinstance([], object) 0164 True 0165 >>> 0166 0167 Under the new proposal, the __methods__ attribute no longer exists: 0168 0169 >>> [].__methods__ 0170 Traceback (most recent call last): 0171 File "<stdin>", line 1, in ? 0172 AttributeError: 'list' object has no attribute '__methods__' 0173 >>> 0174 0175 Instead, you can get the same information from the list type: 0176 0177 >>> pprint.pprint(dir(list)) # like list.__dict__.keys(), but sorted 0178 ['__add__', 0179 '__class__', 0180 '__contains__', 0181 '__delattr__', 0182 '__delitem__', 0183 '__delslice__', 0184 '__doc__', 0185 '__eq__', 0186 '__ge__', 0187 '__getattribute__', 0188 '__getitem__', 0189 '__getslice__', 0190 '__gt__', 0191 '__hash__', 0192 '__iadd__', 0193 '__imul__', 0194 '__init__', 0195 '__iter__', 0196 '__le__', 0197 '__len__', 0198 '__lt__', 0199 '__mul__', 0200 '__ne__', 0201 '__new__', 0202 '__reduce__', 0203 '__reduce_ex__', 0204 '__repr__', 0205 '__reversed__', 0206 '__rmul__', 0207 '__setattr__', 0208 '__setitem__', 0209 '__setslice__', 0210 '__str__', 0211 'append', 0212 'count', 0213 'extend', 0214 'index', 0215 'insert', 0216 'pop', 0217 'remove', 0218 'reverse', 0219 'sort'] 0220 0221 The new introspection API gives more information than the old one: in 0222 addition to the regular methods, it also shows the methods that are 0223 normally invoked through special notations, e.g. __iadd__ (+=), __len__ 0224 (len), __ne__ (!=). You can invoke any method from this list directly: 0225 0226 >>> a = ['tic', 'tac'] 0227 >>> list.__len__(a) # same as len(a) 0228 2 0229 >>> a.__len__() # ditto 0230 2 0231 >>> list.append(a, 'toe') # same as a.append('toe') 0232 >>> a 0233 ['tic', 'tac', 'toe'] 0234 >>> 0235 0236 This is just like it is for user-defined classes. 0237 """ 0238 0239 test_4 = """ 0240 0241 Static methods and class methods 0242 0243 The new introspection API makes it possible to add static methods and class 0244 methods. Static methods are easy to describe: they behave pretty much like 0245 static methods in C++ or Java. Here's an example: 0246 0247 >>> class C: 0248 ... 0249 ... def foo(x, y): 0250 ... print "staticmethod", x, y 0251 ... foo = staticmethod(foo) 0252 0253 >>> C.foo(1, 2) 0254 staticmethod 1 2 0255 >>> c = C() 0256 >>> c.foo(1, 2) 0257 staticmethod 1 2 0258 0259 Class methods use a similar pattern to declare methods that receive an 0260 implicit first argument that is the *class* for which they are invoked. 0261 0262 >>> class C: 0263 ... def foo(cls, y): 0264 ... print "classmethod", cls, y 0265 ... foo = classmethod(foo) 0266 0267 >>> C.foo(1) 0268 classmethod test.test_descrtut.C 1 0269 >>> c = C() 0270 >>> c.foo(1) 0271 classmethod test.test_descrtut.C 1 0272 0273 >>> class D(C): 0274 ... pass 0275 0276 >>> D.foo(1) 0277 classmethod test.test_descrtut.D 1 0278 >>> d = D() 0279 >>> d.foo(1) 0280 classmethod test.test_descrtut.D 1 0281 0282 This prints "classmethod __main__.D 1" both times; in other words, the 0283 class passed as the first argument of foo() is the class involved in the 0284 call, not the class involved in the definition of foo(). 0285 0286 But notice this: 0287 0288 >>> class E(C): 0289 ... def foo(cls, y): # override C.foo 0290 ... print "E.foo() called" 0291 ... C.foo(y) 0292 ... foo = classmethod(foo) 0293 0294 >>> E.foo(1) 0295 E.foo() called 0296 classmethod test.test_descrtut.C 1 0297 >>> e = E() 0298 >>> e.foo(1) 0299 E.foo() called 0300 classmethod test.test_descrtut.C 1 0301 0302 In this example, the call to C.foo() from E.foo() will see class C as its 0303 first argument, not class E. This is to be expected, since the call 0304 specifies the class C. But it stresses the difference between these class 0305 methods and methods defined in metaclasses (where an upcall to a metamethod 0306 would pass the target class as an explicit first argument). 0307 """ 0308 0309 test_5 = """ 0310 0311 Attributes defined by get/set methods 0312 0313 0314 >>> class property(object): 0315 ... 0316 ... def __init__(self, get, set=None): 0317 ... self.__get = get 0318 ... self.__set = set 0319 ... 0320 ... def __get__(self, inst, type=None): 0321 ... return self.__get(inst) 0322 ... 0323 ... def __set__(self, inst, value): 0324 ... if self.__set is None: 0325 ... raise AttributeError, "this attribute is read-only" 0326 ... return self.__set(inst, value) 0327 0328 Now let's define a class with an attribute x defined by a pair of methods, 0329 getx() and and setx(): 0330 0331 >>> class C(object): 0332 ... 0333 ... def __init__(self): 0334 ... self.__x = 0 0335 ... 0336 ... def getx(self): 0337 ... return self.__x 0338 ... 0339 ... def setx(self, x): 0340 ... if x < 0: x = 0 0341 ... self.__x = x 0342 ... 0343 ... x = property(getx, setx) 0344 0345 Here's a small demonstration: 0346 0347 >>> a = C() 0348 >>> a.x = 10 0349 >>> print a.x 0350 10 0351 >>> a.x = -10 0352 >>> print a.x 0353 0 0354 >>> 0355 0356 Hmm -- property is builtin now, so let's try it that way too. 0357 0358 >>> del property # unmask the builtin 0359 >>> property 0360 <type 'property'> 0361 0362 >>> class C(object): 0363 ... def __init__(self): 0364 ... self.__x = 0 0365 ... def getx(self): 0366 ... return self.__x 0367 ... def setx(self, x): 0368 ... if x < 0: x = 0 0369 ... self.__x = x 0370 ... x = property(getx, setx) 0371 0372 0373 >>> a = C() 0374 >>> a.x = 10 0375 >>> print a.x 0376 10 0377 >>> a.x = -10 0378 >>> print a.x 0379 0 0380 >>> 0381 """ 0382 0383 test_6 = """ 0384 0385 Method resolution order 0386 0387 This example is implicit in the writeup. 0388 0389 >>> class A: # classic class 0390 ... def save(self): 0391 ... print "called A.save()" 0392 >>> class B(A): 0393 ... pass 0394 >>> class C(A): 0395 ... def save(self): 0396 ... print "called C.save()" 0397 >>> class D(B, C): 0398 ... pass 0399 0400 >>> D().save() 0401 called A.save() 0402 0403 >>> class A(object): # new class 0404 ... def save(self): 0405 ... print "called A.save()" 0406 >>> class B(A): 0407 ... pass 0408 >>> class C(A): 0409 ... def save(self): 0410 ... print "called C.save()" 0411 >>> class D(B, C): 0412 ... pass 0413 0414 >>> D().save() 0415 called C.save() 0416 """ 0417 0418 class A(object): 0419 def m(self): 0420 return "A" 0421 0422 class B(A): 0423 def m(self): 0424 return "B" + super(B, self).m() 0425 0426 class C(A): 0427 def m(self): 0428 return "C" + super(C, self).m() 0429 0430 class D(C, B): 0431 def m(self): 0432 return "D" + super(D, self).m() 0433 0434 0435 test_7 = """ 0436 0437 Cooperative methods and "super" 0438 0439 >>> print D().m() # "DCBA" 0440 DCBA 0441 """ 0442 0443 test_8 = """ 0444 0445 Backwards incompatibilities 0446 0447 >>> class A: 0448 ... def foo(self): 0449 ... print "called A.foo()" 0450 0451 >>> class B(A): 0452 ... pass 0453 0454 >>> class C(A): 0455 ... def foo(self): 0456 ... B.foo(self) 0457 0458 >>> C().foo() 0459 Traceback (most recent call last): 0460 ... 0461 TypeError: unbound method foo() must be called with B instance as first argument (got C instance instead) 0462 0463 >>> class C(A): 0464 ... def foo(self): 0465 ... A.foo(self) 0466 >>> C().foo() 0467 called A.foo() 0468 """ 0469 0470 __test__ = {"tut1": test_1, 0471 "tut2": test_2, 0472 "tut3": test_3, 0473 "tut4": test_4, 0474 "tut5": test_5, 0475 "tut6": test_6, 0476 "tut7": test_7, 0477 "tut8": test_8} 0478 0479 # Magic test name that regrtest.py invokes *after* importing this module. 0480 # This worms around a bootstrap problem. 0481 # Note that doctest and regrtest both look in sys.argv for a "-v" argument, 0482 # so this works as expected in both ways of running regrtest. 0483 def test_main(verbose=None): 0484 # Obscure: import this module as test.test_descrtut instead of as 0485 # plain test_descrtut because the name of this module works its way 0486 # into the doctest examples, and unless the full test.test_descrtut 0487 # business is used the name can change depending on how the test is 0488 # invoked. 0489 from test import test_support, test_descrtut 0490 test_support.run_doctest(test_descrtut, verbose) 0491 0492 # This part isn't needed for regrtest, but for running the test directly. 0493 if __name__ == "__main__": 0494 test_main(1) 0495
Generated by PyXR 0.9.4