Home | History | Annotate | Download | only in test
      1 # This contains most of the executable examples from Guido's descr
      2 # tutorial, once at
      3 #
      4 #     http://www.python.org/2.2/descrintro.html
      5 #
      6 # A few examples left implicit in the writeup were fleshed out, a few were
      7 # skipped due to lack of interest (e.g., faking super() by hand isn't
      8 # of much interest anymore), and a few were fiddled to make the output
      9 # deterministic.
     10 
     11 from test.test_support import sortdict
     12 import pprint
     13 
     14 class defaultdict(dict):
     15     def __init__(self, default=None):
     16         dict.__init__(self)
     17         self.default = default
     18 
     19     def __getitem__(self, key):
     20         try:
     21             return dict.__getitem__(self, key)
     22         except KeyError:
     23             return self.default
     24 
     25     def get(self, key, *args):
     26         if not args:
     27             args = (self.default,)
     28         return dict.get(self, key, *args)
     29 
     30     def merge(self, other):
     31         for key in other:
     32             if key not in self:
     33                 self[key] = other[key]
     34 
     35 test_1 = """
     36 
     37 Here's the new type at work:
     38 
     39     >>> print defaultdict               # show our type
     40     <class 'test.test_descrtut.defaultdict'>
     41     >>> print type(defaultdict)         # its metatype
     42     <type 'type'>
     43     >>> a = defaultdict(default=0.0)    # create an instance
     44     >>> print a                         # show the instance
     45     {}
     46     >>> print type(a)                   # show its type
     47     <class 'test.test_descrtut.defaultdict'>
     48     >>> print a.__class__               # show its class
     49     <class 'test.test_descrtut.defaultdict'>
     50     >>> print type(a) is a.__class__    # its type is its class
     51     True
     52     >>> a[1] = 3.25                     # modify the instance
     53     >>> print a                         # show the new value
     54     {1: 3.25}
     55     >>> print a[1]                      # show the new item
     56     3.25
     57     >>> print a[0]                      # a non-existent item
     58     0.0
     59     >>> a.merge({1:100, 2:200})         # use a dict method
     60     >>> print sortdict(a)               # show the result
     61     {1: 3.25, 2: 200}
     62     >>>
     63 
     64 We can also use the new type in contexts where classic only allows "real"
     65 dictionaries, such as the locals/globals dictionaries for the exec
     66 statement or the built-in function eval():
     67 
     68     >>> def sorted(seq):
     69     ...     seq.sort(key=str)
     70     ...     return seq
     71     >>> print sorted(a.keys())
     72     [1, 2]
     73     >>> exec "x = 3; print x" in a
     74     3
     75     >>> print sorted(a.keys())
     76     [1, 2, '__builtins__', 'x']
     77     >>> print a['x']
     78     3
     79     >>>
     80 
     81 Now I'll show that defaultdict instances have dynamic instance variables,
     82 just like classic classes:
     83 
     84     >>> a.default = -1
     85     >>> print a["noway"]
     86     -1
     87     >>> a.default = -1000
     88     >>> print a["noway"]
     89     -1000
     90     >>> 'default' in dir(a)
     91     True
     92     >>> a.x1 = 100
     93     >>> a.x2 = 200
     94     >>> print a.x1
     95     100
     96     >>> d = dir(a)
     97     >>> 'default' in d and 'x1' in d and 'x2' in d
     98     True
     99     >>> print sortdict(a.__dict__)
    100     {'default': -1000, 'x1': 100, 'x2': 200}
    101     >>>
    102 """
    103 
    104 class defaultdict2(dict):
    105     __slots__ = ['default']
    106 
    107     def __init__(self, default=None):
    108         dict.__init__(self)
    109         self.default = default
    110 
    111     def __getitem__(self, key):
    112         try:
    113             return dict.__getitem__(self, key)
    114         except KeyError:
    115             return self.default
    116 
    117     def get(self, key, *args):
    118         if not args:
    119             args = (self.default,)
    120         return dict.get(self, key, *args)
    121 
    122     def merge(self, other):
    123         for key in other:
    124             if key not in self:
    125                 self[key] = other[key]
    126 
    127 test_2 = """
    128 
    129 The __slots__ declaration takes a list of instance variables, and reserves
    130 space for exactly these in the instance. When __slots__ is used, other
    131 instance variables cannot be assigned to:
    132 
    133     >>> a = defaultdict2(default=0.0)
    134     >>> a[1]
    135     0.0
    136     >>> a.default = -1
    137     >>> a[1]
    138     -1
    139     >>> a.x1 = 1
    140     Traceback (most recent call last):
    141       File "<stdin>", line 1, in ?
    142     AttributeError: 'defaultdict2' object has no attribute 'x1'
    143     >>>
    144 
    145 """
    146 
    147 test_3 = """
    148 
    149 Introspecting instances of built-in types
    150 
    151 For instance of built-in types, x.__class__ is now the same as type(x):
    152 
    153     >>> type([])
    154     <type 'list'>
    155     >>> [].__class__
    156     <type 'list'>
    157     >>> list
    158     <type 'list'>
    159     >>> isinstance([], list)
    160     True
    161     >>> isinstance([], dict)
    162     False
    163     >>> isinstance([], object)
    164     True
    165     >>>
    166 
    167 Under the new proposal, the __methods__ attribute no longer exists:
    168 
    169     >>> [].__methods__
    170     Traceback (most recent call last):
    171       File "<stdin>", line 1, in ?
    172     AttributeError: 'list' object has no attribute '__methods__'
    173     >>>
    174 
    175 Instead, you can get the same information from the list type:
    176 
    177     >>> pprint.pprint(dir(list))    # like list.__dict__.keys(), but sorted
    178     ['__add__',
    179      '__class__',
    180      '__contains__',
    181      '__delattr__',
    182      '__delitem__',
    183      '__delslice__',
    184      '__doc__',
    185      '__eq__',
    186      '__format__',
    187      '__ge__',
    188      '__getattribute__',
    189      '__getitem__',
    190      '__getslice__',
    191      '__gt__',
    192      '__hash__',
    193      '__iadd__',
    194      '__imul__',
    195      '__init__',
    196      '__iter__',
    197      '__le__',
    198      '__len__',
    199      '__lt__',
    200      '__mul__',
    201      '__ne__',
    202      '__new__',
    203      '__reduce__',
    204      '__reduce_ex__',
    205      '__repr__',
    206      '__reversed__',
    207      '__rmul__',
    208      '__setattr__',
    209      '__setitem__',
    210      '__setslice__',
    211      '__sizeof__',
    212      '__str__',
    213      '__subclasshook__',
    214      'append',
    215      'count',
    216      'extend',
    217      'index',
    218      'insert',
    219      'pop',
    220      'remove',
    221      'reverse',
    222      'sort']
    223 
    224 The new introspection API gives more information than the old one:  in
    225 addition to the regular methods, it also shows the methods that are
    226 normally invoked through special notations, e.g. __iadd__ (+=), __len__
    227 (len), __ne__ (!=). You can invoke any method from this list directly:
    228 
    229     >>> a = ['tic', 'tac']
    230     >>> list.__len__(a)          # same as len(a)
    231     2
    232     >>> a.__len__()              # ditto
    233     2
    234     >>> list.append(a, 'toe')    # same as a.append('toe')
    235     >>> a
    236     ['tic', 'tac', 'toe']
    237     >>>
    238 
    239 This is just like it is for user-defined classes.
    240 """
    241 
    242 test_4 = """
    243 
    244 Static methods and class methods
    245 
    246 The new introspection API makes it possible to add static methods and class
    247 methods. Static methods are easy to describe: they behave pretty much like
    248 static methods in C++ or Java. Here's an example:
    249 
    250     >>> class C:
    251     ...
    252     ...     @staticmethod
    253     ...     def foo(x, y):
    254     ...         print "staticmethod", x, y
    255 
    256     >>> C.foo(1, 2)
    257     staticmethod 1 2
    258     >>> c = C()
    259     >>> c.foo(1, 2)
    260     staticmethod 1 2
    261 
    262 Class methods use a similar pattern to declare methods that receive an
    263 implicit first argument that is the *class* for which they are invoked.
    264 
    265     >>> class C:
    266     ...     @classmethod
    267     ...     def foo(cls, y):
    268     ...         print "classmethod", cls, y
    269 
    270     >>> C.foo(1)
    271     classmethod test.test_descrtut.C 1
    272     >>> c = C()
    273     >>> c.foo(1)
    274     classmethod test.test_descrtut.C 1
    275 
    276     >>> class D(C):
    277     ...     pass
    278 
    279     >>> D.foo(1)
    280     classmethod test.test_descrtut.D 1
    281     >>> d = D()
    282     >>> d.foo(1)
    283     classmethod test.test_descrtut.D 1
    284 
    285 This prints "classmethod __main__.D 1" both times; in other words, the
    286 class passed as the first argument of foo() is the class involved in the
    287 call, not the class involved in the definition of foo().
    288 
    289 But notice this:
    290 
    291     >>> class E(C):
    292     ...     @classmethod
    293     ...     def foo(cls, y): # override C.foo
    294     ...         print "E.foo() called"
    295     ...         C.foo(y)
    296 
    297     >>> E.foo(1)
    298     E.foo() called
    299     classmethod test.test_descrtut.C 1
    300     >>> e = E()
    301     >>> e.foo(1)
    302     E.foo() called
    303     classmethod test.test_descrtut.C 1
    304 
    305 In this example, the call to C.foo() from E.foo() will see class C as its
    306 first argument, not class E. This is to be expected, since the call
    307 specifies the class C. But it stresses the difference between these class
    308 methods and methods defined in metaclasses (where an upcall to a metamethod
    309 would pass the target class as an explicit first argument).
    310 """
    311 
    312 test_5 = """
    313 
    314 Attributes defined by get/set methods
    315 
    316 
    317     >>> class property(object):
    318     ...
    319     ...     def __init__(self, get, set=None):
    320     ...         self.__get = get
    321     ...         self.__set = set
    322     ...
    323     ...     def __get__(self, inst, type=None):
    324     ...         return self.__get(inst)
    325     ...
    326     ...     def __set__(self, inst, value):
    327     ...         if self.__set is None:
    328     ...             raise AttributeError, "this attribute is read-only"
    329     ...         return self.__set(inst, value)
    330 
    331 Now let's define a class with an attribute x defined by a pair of methods,
    332 getx() and setx():
    333 
    334     >>> class C(object):
    335     ...
    336     ...     def __init__(self):
    337     ...         self.__x = 0
    338     ...
    339     ...     def getx(self):
    340     ...         return self.__x
    341     ...
    342     ...     def setx(self, x):
    343     ...         if x < 0: x = 0
    344     ...         self.__x = x
    345     ...
    346     ...     x = property(getx, setx)
    347 
    348 Here's a small demonstration:
    349 
    350     >>> a = C()
    351     >>> a.x = 10
    352     >>> print a.x
    353     10
    354     >>> a.x = -10
    355     >>> print a.x
    356     0
    357     >>>
    358 
    359 Hmm -- property is builtin now, so let's try it that way too.
    360 
    361     >>> del property  # unmask the builtin
    362     >>> property
    363     <type 'property'>
    364 
    365     >>> class C(object):
    366     ...     def __init__(self):
    367     ...         self.__x = 0
    368     ...     def getx(self):
    369     ...         return self.__x
    370     ...     def setx(self, x):
    371     ...         if x < 0: x = 0
    372     ...         self.__x = x
    373     ...     x = property(getx, setx)
    374 
    375 
    376     >>> a = C()
    377     >>> a.x = 10
    378     >>> print a.x
    379     10
    380     >>> a.x = -10
    381     >>> print a.x
    382     0
    383     >>>
    384 """
    385 
    386 test_6 = """
    387 
    388 Method resolution order
    389 
    390 This example is implicit in the writeup.
    391 
    392 >>> class A:    # classic class
    393 ...     def save(self):
    394 ...         print "called A.save()"
    395 >>> class B(A):
    396 ...     pass
    397 >>> class C(A):
    398 ...     def save(self):
    399 ...         print "called C.save()"
    400 >>> class D(B, C):
    401 ...     pass
    402 
    403 >>> D().save()
    404 called A.save()
    405 
    406 >>> class A(object):  # new class
    407 ...     def save(self):
    408 ...         print "called A.save()"
    409 >>> class B(A):
    410 ...     pass
    411 >>> class C(A):
    412 ...     def save(self):
    413 ...         print "called C.save()"
    414 >>> class D(B, C):
    415 ...     pass
    416 
    417 >>> D().save()
    418 called C.save()
    419 """
    420 
    421 class A(object):
    422     def m(self):
    423         return "A"
    424 
    425 class B(A):
    426     def m(self):
    427         return "B" + super(B, self).m()
    428 
    429 class C(A):
    430     def m(self):
    431         return "C" + super(C, self).m()
    432 
    433 class D(C, B):
    434     def m(self):
    435         return "D" + super(D, self).m()
    436 
    437 
    438 test_7 = """
    439 
    440 Cooperative methods and "super"
    441 
    442 >>> print D().m() # "DCBA"
    443 DCBA
    444 """
    445 
    446 test_8 = """
    447 
    448 Backwards incompatibilities
    449 
    450 >>> class A:
    451 ...     def foo(self):
    452 ...         print "called A.foo()"
    453 
    454 >>> class B(A):
    455 ...     pass
    456 
    457 >>> class C(A):
    458 ...     def foo(self):
    459 ...         B.foo(self)
    460 
    461 >>> C().foo()
    462 Traceback (most recent call last):
    463  ...
    464 TypeError: unbound method foo() must be called with B instance as first argument (got C instance instead)
    465 
    466 >>> class C(A):
    467 ...     def foo(self):
    468 ...         A.foo(self)
    469 >>> C().foo()
    470 called A.foo()
    471 """
    472 
    473 __test__ = {"tut1": test_1,
    474             "tut2": test_2,
    475             "tut3": test_3,
    476             "tut4": test_4,
    477             "tut5": test_5,
    478             "tut6": test_6,
    479             "tut7": test_7,
    480             "tut8": test_8}
    481 
    482 # Magic test name that regrtest.py invokes *after* importing this module.
    483 # This worms around a bootstrap problem.
    484 # Note that doctest and regrtest both look in sys.argv for a "-v" argument,
    485 # so this works as expected in both ways of running regrtest.
    486 def test_main(verbose=None):
    487     # Obscure:  import this module as test.test_descrtut instead of as
    488     # plain test_descrtut because the name of this module works its way
    489     # into the doctest examples, and unless the full test.test_descrtut
    490     # business is used the name can change depending on how the test is
    491     # invoked.
    492     from test import test_support, test_descrtut
    493     test_support.run_doctest(test_descrtut, verbose)
    494 
    495 # This part isn't needed for regrtest, but for running the test directly.
    496 if __name__ == "__main__":
    497     test_main(1)
    498