diff options
Diffstat (limited to 'lib/python2.7/test/test_descrtut.py')
-rw-r--r-- | lib/python2.7/test/test_descrtut.py | 497 |
1 files changed, 0 insertions, 497 deletions
diff --git a/lib/python2.7/test/test_descrtut.py b/lib/python2.7/test/test_descrtut.py deleted file mode 100644 index 33ff0c8..0000000 --- a/lib/python2.7/test/test_descrtut.py +++ /dev/null @@ -1,497 +0,0 @@ -# This contains most of the executable examples from Guido's descr -# tutorial, once at -# -# http://www.python.org/2.2/descrintro.html -# -# A few examples left implicit in the writeup were fleshed out, a few were -# skipped due to lack of interest (e.g., faking super() by hand isn't -# of much interest anymore), and a few were fiddled to make the output -# deterministic. - -from test.test_support import sortdict -import pprint - -class defaultdict(dict): - def __init__(self, default=None): - dict.__init__(self) - self.default = default - - def __getitem__(self, key): - try: - return dict.__getitem__(self, key) - except KeyError: - return self.default - - def get(self, key, *args): - if not args: - args = (self.default,) - return dict.get(self, key, *args) - - def merge(self, other): - for key in other: - if key not in self: - self[key] = other[key] - -test_1 = """ - -Here's the new type at work: - - >>> print defaultdict # show our type - <class 'test.test_descrtut.defaultdict'> - >>> print type(defaultdict) # its metatype - <type 'type'> - >>> a = defaultdict(default=0.0) # create an instance - >>> print a # show the instance - {} - >>> print type(a) # show its type - <class 'test.test_descrtut.defaultdict'> - >>> print a.__class__ # show its class - <class 'test.test_descrtut.defaultdict'> - >>> print type(a) is a.__class__ # its type is its class - True - >>> a[1] = 3.25 # modify the instance - >>> print a # show the new value - {1: 3.25} - >>> print a[1] # show the new item - 3.25 - >>> print a[0] # a non-existent item - 0.0 - >>> a.merge({1:100, 2:200}) # use a dict method - >>> print sortdict(a) # show the result - {1: 3.25, 2: 200} - >>> - -We can also use the new type in contexts where classic only allows "real" -dictionaries, such as the locals/globals dictionaries for the exec -statement or the built-in function eval(): - - >>> def sorted(seq): - ... seq.sort(key=str) - ... return seq - >>> print sorted(a.keys()) - [1, 2] - >>> exec "x = 3; print x" in a - 3 - >>> print sorted(a.keys()) - [1, 2, '__builtins__', 'x'] - >>> print a['x'] - 3 - >>> - -Now I'll show that defaultdict instances have dynamic instance variables, -just like classic classes: - - >>> a.default = -1 - >>> print a["noway"] - -1 - >>> a.default = -1000 - >>> print a["noway"] - -1000 - >>> 'default' in dir(a) - True - >>> a.x1 = 100 - >>> a.x2 = 200 - >>> print a.x1 - 100 - >>> d = dir(a) - >>> 'default' in d and 'x1' in d and 'x2' in d - True - >>> print sortdict(a.__dict__) - {'default': -1000, 'x1': 100, 'x2': 200} - >>> -""" - -class defaultdict2(dict): - __slots__ = ['default'] - - def __init__(self, default=None): - dict.__init__(self) - self.default = default - - def __getitem__(self, key): - try: - return dict.__getitem__(self, key) - except KeyError: - return self.default - - def get(self, key, *args): - if not args: - args = (self.default,) - return dict.get(self, key, *args) - - def merge(self, other): - for key in other: - if key not in self: - self[key] = other[key] - -test_2 = """ - -The __slots__ declaration takes a list of instance variables, and reserves -space for exactly these in the instance. When __slots__ is used, other -instance variables cannot be assigned to: - - >>> a = defaultdict2(default=0.0) - >>> a[1] - 0.0 - >>> a.default = -1 - >>> a[1] - -1 - >>> a.x1 = 1 - Traceback (most recent call last): - File "<stdin>", line 1, in ? - AttributeError: 'defaultdict2' object has no attribute 'x1' - >>> - -""" - -test_3 = """ - -Introspecting instances of built-in types - -For instance of built-in types, x.__class__ is now the same as type(x): - - >>> type([]) - <type 'list'> - >>> [].__class__ - <type 'list'> - >>> list - <type 'list'> - >>> isinstance([], list) - True - >>> isinstance([], dict) - False - >>> isinstance([], object) - True - >>> - -Under the new proposal, the __methods__ attribute no longer exists: - - >>> [].__methods__ - Traceback (most recent call last): - File "<stdin>", line 1, in ? - AttributeError: 'list' object has no attribute '__methods__' - >>> - -Instead, you can get the same information from the list type: - - >>> pprint.pprint(dir(list)) # like list.__dict__.keys(), but sorted - ['__add__', - '__class__', - '__contains__', - '__delattr__', - '__delitem__', - '__delslice__', - '__doc__', - '__eq__', - '__format__', - '__ge__', - '__getattribute__', - '__getitem__', - '__getslice__', - '__gt__', - '__hash__', - '__iadd__', - '__imul__', - '__init__', - '__iter__', - '__le__', - '__len__', - '__lt__', - '__mul__', - '__ne__', - '__new__', - '__reduce__', - '__reduce_ex__', - '__repr__', - '__reversed__', - '__rmul__', - '__setattr__', - '__setitem__', - '__setslice__', - '__sizeof__', - '__str__', - '__subclasshook__', - 'append', - 'count', - 'extend', - 'index', - 'insert', - 'pop', - 'remove', - 'reverse', - 'sort'] - -The new introspection API gives more information than the old one: in -addition to the regular methods, it also shows the methods that are -normally invoked through special notations, e.g. __iadd__ (+=), __len__ -(len), __ne__ (!=). You can invoke any method from this list directly: - - >>> a = ['tic', 'tac'] - >>> list.__len__(a) # same as len(a) - 2 - >>> a.__len__() # ditto - 2 - >>> list.append(a, 'toe') # same as a.append('toe') - >>> a - ['tic', 'tac', 'toe'] - >>> - -This is just like it is for user-defined classes. -""" - -test_4 = """ - -Static methods and class methods - -The new introspection API makes it possible to add static methods and class -methods. Static methods are easy to describe: they behave pretty much like -static methods in C++ or Java. Here's an example: - - >>> class C: - ... - ... @staticmethod - ... def foo(x, y): - ... print "staticmethod", x, y - - >>> C.foo(1, 2) - staticmethod 1 2 - >>> c = C() - >>> c.foo(1, 2) - staticmethod 1 2 - -Class methods use a similar pattern to declare methods that receive an -implicit first argument that is the *class* for which they are invoked. - - >>> class C: - ... @classmethod - ... def foo(cls, y): - ... print "classmethod", cls, y - - >>> C.foo(1) - classmethod test.test_descrtut.C 1 - >>> c = C() - >>> c.foo(1) - classmethod test.test_descrtut.C 1 - - >>> class D(C): - ... pass - - >>> D.foo(1) - classmethod test.test_descrtut.D 1 - >>> d = D() - >>> d.foo(1) - classmethod test.test_descrtut.D 1 - -This prints "classmethod __main__.D 1" both times; in other words, the -class passed as the first argument of foo() is the class involved in the -call, not the class involved in the definition of foo(). - -But notice this: - - >>> class E(C): - ... @classmethod - ... def foo(cls, y): # override C.foo - ... print "E.foo() called" - ... C.foo(y) - - >>> E.foo(1) - E.foo() called - classmethod test.test_descrtut.C 1 - >>> e = E() - >>> e.foo(1) - E.foo() called - classmethod test.test_descrtut.C 1 - -In this example, the call to C.foo() from E.foo() will see class C as its -first argument, not class E. This is to be expected, since the call -specifies the class C. But it stresses the difference between these class -methods and methods defined in metaclasses (where an upcall to a metamethod -would pass the target class as an explicit first argument). -""" - -test_5 = """ - -Attributes defined by get/set methods - - - >>> class property(object): - ... - ... def __init__(self, get, set=None): - ... self.__get = get - ... self.__set = set - ... - ... def __get__(self, inst, type=None): - ... return self.__get(inst) - ... - ... def __set__(self, inst, value): - ... if self.__set is None: - ... raise AttributeError, "this attribute is read-only" - ... return self.__set(inst, value) - -Now let's define a class with an attribute x defined by a pair of methods, -getx() and setx(): - - >>> class C(object): - ... - ... def __init__(self): - ... self.__x = 0 - ... - ... def getx(self): - ... return self.__x - ... - ... def setx(self, x): - ... if x < 0: x = 0 - ... self.__x = x - ... - ... x = property(getx, setx) - -Here's a small demonstration: - - >>> a = C() - >>> a.x = 10 - >>> print a.x - 10 - >>> a.x = -10 - >>> print a.x - 0 - >>> - -Hmm -- property is builtin now, so let's try it that way too. - - >>> del property # unmask the builtin - >>> property - <type 'property'> - - >>> class C(object): - ... def __init__(self): - ... self.__x = 0 - ... def getx(self): - ... return self.__x - ... def setx(self, x): - ... if x < 0: x = 0 - ... self.__x = x - ... x = property(getx, setx) - - - >>> a = C() - >>> a.x = 10 - >>> print a.x - 10 - >>> a.x = -10 - >>> print a.x - 0 - >>> -""" - -test_6 = """ - -Method resolution order - -This example is implicit in the writeup. - ->>> class A: # classic class -... def save(self): -... print "called A.save()" ->>> class B(A): -... pass ->>> class C(A): -... def save(self): -... print "called C.save()" ->>> class D(B, C): -... pass - ->>> D().save() -called A.save() - ->>> class A(object): # new class -... def save(self): -... print "called A.save()" ->>> class B(A): -... pass ->>> class C(A): -... def save(self): -... print "called C.save()" ->>> class D(B, C): -... pass - ->>> D().save() -called C.save() -""" - -class A(object): - def m(self): - return "A" - -class B(A): - def m(self): - return "B" + super(B, self).m() - -class C(A): - def m(self): - return "C" + super(C, self).m() - -class D(C, B): - def m(self): - return "D" + super(D, self).m() - - -test_7 = """ - -Cooperative methods and "super" - ->>> print D().m() # "DCBA" -DCBA -""" - -test_8 = """ - -Backwards incompatibilities - ->>> class A: -... def foo(self): -... print "called A.foo()" - ->>> class B(A): -... pass - ->>> class C(A): -... def foo(self): -... B.foo(self) - ->>> C().foo() -Traceback (most recent call last): - ... -TypeError: unbound method foo() must be called with B instance as first argument (got C instance instead) - ->>> class C(A): -... def foo(self): -... A.foo(self) ->>> C().foo() -called A.foo() -""" - -__test__ = {"tut1": test_1, - "tut2": test_2, - "tut3": test_3, - "tut4": test_4, - "tut5": test_5, - "tut6": test_6, - "tut7": test_7, - "tut8": test_8} - -# Magic test name that regrtest.py invokes *after* importing this module. -# This worms around a bootstrap problem. -# Note that doctest and regrtest both look in sys.argv for a "-v" argument, -# so this works as expected in both ways of running regrtest. -def test_main(verbose=None): - # Obscure: import this module as test.test_descrtut instead of as - # plain test_descrtut because the name of this module works its way - # into the doctest examples, and unless the full test.test_descrtut - # business is used the name can change depending on how the test is - # invoked. - from test import test_support, test_descrtut - test_support.run_doctest(test_descrtut, verbose) - -# This part isn't needed for regrtest, but for running the test directly. -if __name__ == "__main__": - test_main(1) |