symbian-qemu-0.9.1-12/python-2.6.1/Lib/test/test_descrtut.py
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     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-existant 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()
       
    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 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)