home *** CD-ROM | disk | FTP | other *** search
/ PC World 2005 June / PCWorld_2005-06_cd.bin / software / vyzkuste / firewally / firewally.exe / framework-2.3.exe / test_descrtut.py < prev    next >
Text File  |  2003-12-30  |  12KB  |  504 lines

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