ch31类的高级主题(python)

### file: setwrapper.py

class Set:
   def __init__(self, value = []):    # Constructor
       self.data = []                 # Manages a list
       self.concat(value)

   def intersect(self, other):        # other is any sequence
       res = []                       # self is the subject
       for x in self.data:
           if x in other:             # Pick common items
               res.append(x)
       return Set(res)                # Return a new Set

   def union(self, other):            # other is any sequence
       res = self.data[:]             # Copy of my list
       for x in other:                # Add items in other
           if not x in res:
               res.append(x)
       return Set(res)

   def concat(self, value):           # value: list, Set...
       for x in value:                # Removes duplicates
          if not x in self.data:
               self.data.append(x)

   def __len__(self):          return len(self.data)            # len(self)
   def __getitem__(self, key): return self.data[key]            # self[i]
   def __and__(self, other):   return self.intersect(other)     # self & other
   def __or__(self, other):    return self.union(other)         # self | other
   def __repr__(self):         return 'Set:' + repr(self.data)  # print()



x = Set([1, 3, 5, 7])
print(x.union(Set([1, 4, 7])))       # prints Set:[1, 3, 5, 7, 4]
print(x | Set([1, 4, 6]))            # prints Set:[1, 3, 5, 7, 4, 6]



### file: typesubclass.py

# Subclass built-in list type/class
# Map 1..N to 0..N-1; call back to built-in version.

class MyList(list):
    def __getitem__(self, offset):
        print('(indexing %s at %s)' % (self, offset))
        return list.__getitem__(self, offset - 1)

if __name__ == '__main__':
    print(list('abc'))
    x = MyList('abc')               # __init__ inherited from list
    print(x)                        # __repr__ inherited from list

    print(x[1])                     # MyList.__getitem__
    print(x[3])                     # Customizes list superclass method

    x.append('spam'); print(x)      # Attributes from list superclass
    x.reverse();      print(x)



% python typesubclass.py



### file: setsubclass.py

class Set(list):
    def __init__(self, value = []):      # Constructor
        list.__init__([])                # Customizes list
        self.concat(value)               # Copies mutable defaults

    def intersect(self, other):          # other is any sequence
        res = []                         # self is the subject
        for x in self:
            if x in other:               # Pick common items
                res.append(x)
        return Set(res)                  # Return a new Set

    def union(self, other):              # other is any sequence
        res = Set(self)                  # Copy me and my list
        res.concat(other)
        return res

    def concat(self, value):             # value: list, Set . . .
        for x in value:                  # Removes duplicates
            if not x in self:
                self.append(x)

    def __and__(self, other): return self.intersect(other)
    def __or__(self, other):  return self.union(other)
    def __repr__(self):       return 'Set:' + list.__repr__(self)

if __name__ == '__main__':
    x = Set([1,3,5,7])
    y = Set([2,1,4,5,6])
    print(x, y, len(x))
    print(x.intersect(y), y.union(x))
    print(x & y, x | y)
    x.reverse(); print(x)



% python setsubclass.py



C:\misc> c:\python26\python
>>> class C: pass                       # Classic classes in 2.6
...
>>> I = C()
>>> type(I)                             # Instances are made from classes
<type 'instance'>
>>> I.__class__
<class __main__.C at 0x025085A0>

>>> type(C)                             # But classes are not the same as types
<type 'classobj'>
>>> C.__class__
AttributeError: class C has no attribute '__class__'

>>> type([1, 2, 3])
<type 'list'>
>>> type(list)
<type 'type'>
>>> list.__class__
<type 'type'>



C:\misc> c:\python26\python
>>> class C(object): pass               # New-style classes in 2.6
...
>>> I = C()
>>> type(I)                             # Type of instance is class it's made from
<class '__main__.C'>
>>> I.__class__
<class '__main__.C'>

>>> type(C)                             # Classes are user-defined types
<type 'type'>
>>> C.__class__
<type 'type'>

>>> type([1, 2, 3])                     # Built-in types work the same way
<type 'list'>
>>> type(list)
<type 'type'>
>>> list.__class__
<type 'type'>



C:\misc> c:\python30\python
>>> class C: pass                       # All classes are new-style in 3.0
...
>>> I = C()
>>> type(I)                             # Type of instance is class it's made from
<class '__main__.C'>
>>> I.__class__
<class '__main__.C'>

>>> type(C)                             # Class is a type, and type is a class
<class 'type'>
>>> C.__class__
<class 'type'>

>>> type([1, 2, 3])                     # Classes and built-in types work the same
<class 'list'>
>>> type(list)
<class 'type'>
>>> list.__class__
<class 'type'>



C:\misc> c:\python30\python
>>> class C: pass
...
>>> class D: pass
...
>>> c = C()
>>> d = D()
>>> type(c) == type(d)                 # 3.0: compares the instances' classes
False

>>> type(c), type(d)
(<class '__main__.C'>, <class '__main__.D'>)
>>> c.__class__, d.__class__
(<class '__main__.C'>, <class '__main__.D'>)

>>> c1, c2 = C(), C()
>>> type(c1) == type(c2)
True



C:\misc> c:\python26\python
>>> class C: pass
...
>>> class D: pass
...
>>> c = C()
>>> d = D()
>>> type(c) == type(d)                 # 2.6: all instances are same type
True
>>> c.__class__ == d.__class__         # Must compare classes explicitly
False

>>> type(c), type(d)
(<type 'instance'>, <type 'instance'>)
>>> c.__class__, d.__class__
(<class __main__.C at 0x024585A0>, <class __main__.D at 0x024588D0>)



C:\misc> c:\python26\python
>>> class C(object): pass
...
>>> class D(object): pass
...
>>> c = C()
>>> d = D()
>>> type(c) == type(d)                 # 2.6 new-style: same as all in 3.0
False

>>> type(c), type(d)
(<class '__main__.C'>, <class '__main__.D'>)
>>> c.__class__, d.__class__
(<class '__main__.C'>, <class '__main__.D'>)



>>> class C: pass
...
>>> X = C()

>>> type(X)                           # Type is now class instance was created from
<class '__main__.C'>
>>> type(C)
<class 'type'>



>>> isinstance(X, object)
True
>>> isinstance(C, object)             # Classes always inherit from object
True



>>> type('spam')
<class 'str'>
>>> type(str)
<class 'type'>

>>> isinstance('spam', object)        # Same for  built-in types (classes)
True
>>> isinstance(str, object)
True



>>> type(type)                        # All classes are types, and vice versa
<class 'type'>
>>> type(object)
<class 'type'>

>>> isinstance(type, object)          # All classes derive from object, even type
True
>>> isinstance(object, type)          # Types make classes, and type is a class
True
>>> type is object
False



>>> class A:     
        attr = 1         # Classic (Python 2.6)

>>> class B(A):          # B and C both lead to A 
        pass

>>> class C(A): 
        attr = 2

>>> class D(B, C):
        pass             # Tries A before C

>>> x = D()
>>> x.attr               # Searches x, D, B, A
1



>>> class A(object):
        attr = 1         # New-style ("object" not required in 3.0)

>>> class B(A):     
        pass

>>> class C(A):     
        attr = 2

>>> class D(B, C):   
        pass             # Tries C before A

>>> x = D()
>>> x.attr               # Searches x, D, B, C
2



>>> class A:     
        attr = 1         # Classic

>>> class B(A): 
        pass

>>> class C(A): 
        attr = 2

>>> class D(B, C):
        attr = C.attr    # Choose C, to the right

>>> x = D()
>>> x.attr               # Works like new-style (all 3.0)
2



>>> class A(object):
        attr = 1         # New-style

>>> class B(A):
        pass

>>> class C(A):
        attr = 2

>>> class D(B, C):   
        attr = B.attr    # Choose A.attr, above

>>> x = D()
>>> x.attr               # Works like classic (default 2.6)
1



>>> class A:
        def meth(s): print('A.meth')

>>> class C(A):
        def meth(s): print('C.meth')

>>> class B(A):
        pass

>>> class D(B, C): pass            # Use default search order
>>> x = D()                        # Will vary per class type
>>> x.meth()                       # Defaults to classic order in 2.6
A.meth

>>> class D(B, C): meth = C.meth   # Pick C's method: new-style (and 3.0)
>>> x = D()
>>> x.meth()
C.meth

>>> class D(B, C): meth = B.meth   # Pick B's method: classic
>>> x = D()
>>> x.meth()
A.meth



class D(B, C):
    def meth(self):                # Redefine lower
        ...
        C.meth(self)               # Pick C's method by calling



>>> class limiter(object):
...     __slots__ = ['age', 'name', 'job']
...
>>> x = limiter()
>>> x.age                                           # Must assign before use
AttributeError: age

>>> x.age = 40
>>> x.age
40
>>> x.ape = 1000                                    # Illegal: not in __slots__
AttributeError: 'limiter' object has no attribute 'ape'



>>> class C:
...     __slots__ = ['a', 'b']           # __slots__ means no __dict__ by default
...
>>> X = C()
>>> X.a = 1
>>> X.a
1
>>> X.__dict__
AttributeError: 'C' object has no attribute '__dict__'
>>> getattr(X, 'a')
1
>>> setattr(X, 'b', 2)                   # But getattr() and setattr() still work
>>> X.b
2
>>> 'a' in dir(X)                        # And dir() finds slot attributes too
True
>>> 'b' in dir(X)
True



>>> class D:
...     __slots__ = ['a', 'b']
...     def __init__(self): self.d = 4   # Cannot add new names if no __dict__
...
>>> X = D()
AttributeError: 'D' object has no attribute 'd'



>>> class D:
...     __slots__ = ['a', 'b', '__dict__']    # List __dict__ to include one too
...     c = 3                                 # Class attrs work normally
...     def __init__(self): self.d = 4        # d put in __dict__, a in __slots__
...                                          
>>> X = D()                 
>>> X.d
4
>>> X.__dict__                   # Some objects have both __dict__ and __slots__
{'d': 4}                         # getattr() can fetch either type of attr
>>> X.__slots__
['a', 'b', '__dict__']
>>> X.c
3
>>> X.a                          # All instance attrs undefined until assigned
AttributeError: a
>>> X.a = 1
>>> getattr(X, 'a',), getattr(X, 'c'), getattr(X, 'd')
(1, 3, 4)



>>> for attr in list(X.__dict__) + X.__slots__:
...     print(attr, '=>', getattr(X, attr))

d => 4
a => 1
b => 2
__dict__ => {'d': 4}



>>> for attr in list(getattr(X, '__dict__', [])) + getattr(X, '__slots__', []):
...     print(attr, '=>', getattr(X, attr))


d => 4
a => 1
b => 2
__dict__ => {'d': 4}



>>> class E:
...     __slots__ = ['c', 'd']            # Superclass has slots
...
>>> class D(E):                               
...     __slots__ = ['a', '__dict__']     # So does its subclass
...
>>> X = D()
>>> X.a = 1; X.b = 2; X.c = 3             # The instance is the union
>>> X.a, X.c
(1, 3)

>>> E.__slots__                           # But slots are not concatenated
['c', 'd']
>>> D.__slots__
['a', '__dict__']
>>> X.__slots__                           # Instance inherits *lowest* __slots__
['a', '__dict__']
>>> X.__dict__                            # And has its own an attr dict
{'b': 2}

>>> for attr in list(getattr(X, '__dict__', [])) + getattr(X, '__slots__', []):
...     print(attr, '=>', getattr(X, attr))
...
b => 2                                    # Superclass slots missed!
a => 1
__dict__ => {'b': 2}

>>> dir(X)                                # dir() includes all slot names
[...many names omitted... 'a', 'b', 'c', 'd']



>>> class classic:
...     def __getattr__(self, name):
...         if name == 'age':
...             return 40
...         else:
...             raise AttributeError
...
>>> x = classic()
>>> x.age                                 # Runs __getattr__
40
>>> x.name                                # Runs __getattr__
AttributeError



>>> class newprops(object):
...     def getage(self):
...         return 40
...     age = property(getage, None, None, None)  # get, set, del, docs
...
>>> x = newprops()
>>> x.age                                         # Runs getage
40
>>> x.name                                        # Normal fetch
AttributeError: newprops instance has no attribute 'name'



>>> class newprops(object):
...     def getage(self):
...         return 40
...     def setage(self, value):
...         print('set age:', value)
...         self._age = value
...     age = property(getage, setage, None, None)
...
>>> x = newprops()
>>> x.age                                         # Runs getage
40
>>> x.age = 42                                    # Runs setage
set age: 42
>>> x._age                                        # Normal fetch; no getage call
42
>>> x.job = 'trainer'                             # Normal assign; no setage call
>>> x.job                                         # Normal fetch; no getage call
'trainer'



>>> class classic:
...     def __getattr__(self, name):              # On undefined reference
...         if name == 'age':
...             return 40
...         else:
...             raise AttributeError
...     def __setattr__(self, name, value):       # On all assignments
...         print('set:', name, value)
...         if name == 'age':
...             self.__dict__['_age'] = value
...         else:
...             self.__dict__[name] = value
...
>>> x = classic()
>>> x.age                                         # Runs __getattr__
40
>>> x.age = 41                                    # Runs __setattr__
set: age 41
>>> x._age                                        # Defined: no __getattr__ call
41
>>> x.job = 'trainer'                             # Runs __setattr__ again
>>> x.job                                         # Defined: no __getattr__ call



### file: spam.py

class Spam:
    numInstances = 0
    def __init__(self):
        Spam.numInstances = Spam.numInstances + 1
    def printNumInstances():
        print("Number of instances created: ", Spam.numInstances)



C:\misc> c:\python26\python
>>> from spam import Spam
>>> a = Spam()                   # Cannot call unbound class methods in 2.6
>>> b = Spam()                   # Methods expect a self object by default
>>> c = Spam()

>>> Spam.printNumInstances()
TypeError: unbound method printNumInstances() must be called with Spam instance
as first argument (got nothing instead)
>>> a.printNumInstances()
TypeError: printNumInstances() takes no arguments (1 given)



C:\misc> c:\python30\python
>>> from spam import Spam
>>> a = Spam()                       # Can call functions in class in 3.0
>>> b = Spam()                       # Calls through instances still pass a self
>>> c = Spam()

>>> Spam.printNumInstances()         # Differs in 3.0
Number of instances created:  3
>>> a.printNumInstances()
TypeError: printNumInstances() takes no arguments (1 given)



Spam.printNumInstances()             # Fails in 2.6, works in 3.0
instance.printNumInstances()         # Fails in both 2.6 and 3.0



### file spam.py (changed)

def printNumInstances():
    print("Number of instances created: ", Spam.numInstances)

class Spam:
    numInstances = 0
    def __init__(self):
        Spam.numInstances = Spam.numInstances + 1

>>> import spam
>>> a = spam.Spam()
>>> b = spam.Spam()
>>> c = spam.Spam()
>>> spam.printNumInstances()           # But function may be too far removed
Number of instances created:  3        # And cannot be changed via inheritance
>>> spam.Spam.numInstances
3



class Spam:
    numInstances = 0
    def __init__(self):
        Spam.numInstances = Spam.numInstances + 1
    def printNumInstances(self):
        print("Number of instances created: ", Spam.numInstances)

>>> from spam import Spam
>>> a, b, c = Spam(), Spam(), Spam()
>>> a.printNumInstances()
Number of instances created:  3
>>> Spam.printNumInstances(a)
Number of instances created:  3
>>> Spam().printNumInstances()         # But fetching counter changes counter!
Number of instances created:  4



class Methods:
    def imeth(self, x):            # Normal instance method: passed a self
        print(self, x)

    def smeth(x):                  # Static: no instance passed
        print(x)

    def cmeth(cls, x):             # Class: gets class, not instance
        print(cls, x)

    smeth = staticmethod(smeth)    # Make smeth a static method
    cmeth = classmethod(cmeth)     # Make cmeth a class method



>>> obj = Methods()                # Make an instance

>>> obj.imeth(1)                   # Normal method, call through instance
<__main__.Methods object...> 1     # Becomes imeth(obj, 1)

>>> Methods.imeth(obj, 2)          # Normal method, call through class
<__main__.Methods object...> 2     # Instance passed explicitly

>>> Methods.smeth(3)               # Static method, call through class
3                                  # No instance passed or expected

>>> obj.smeth(4)                   # Static method, call through instance
4                                  # Instance not passed

>>> Methods.cmeth(5)               # Class method, call through class
<class '__main__.Methods'> 5       # Becomes cmeth(Methods, 5)

>>> obj.cmeth(6)                   # Class method, call through instance
<class '__main__.Methods'> 6       # Becomes cmeth(Methods, 6)



class Spam:
    numInstances = 0                         # Use static method for class data
    def __init__(self):
        Spam.numInstances += 1
    def printNumInstances():
        print("Number of instances:", Spam.numInstances)
    printNumInstances = staticmethod(printNumInstances)



>>> a = Spam()
>>> b = Spam()
>>> c = Spam()
>>> Spam.printNumInstances()                 # Call as simple function
Number of instances: 3
>>> a.printNumInstances()                    # Instance argument not passed
Number of instances: 3




class Sub(Spam):
    def printNumInstances():                 # Override a static method
        print("Extra stuff...")              # But call back to original
        Spam.printNumInstances()
    printNumInstances = staticmethod(printNumInstances)

>>> a = Sub()
>>> b = Sub()
>>> a.printNumInstances()                    # Call from subclass instance
Extra stuff...
Number of instances: 2
>>> Sub.printNumInstances()                  # Call from subclass itself
Extra stuff...
Number of instances: 2
>>> Spam.printNumInstances()
Number of instances: 2



>>> class Other(Spam): pass                  # Inherit static method verbatim

>>> c = Other()
>>> c.printNumInstances()
Number of instances: 3



class Spam:
    numInstances = 0                         # Use class method instead of static
    def __init__(self):
        Spam.numInstances += 1
    def printNumInstances(cls):
        print("Number of instances:", cls.numInstances)
    printNumInstances = classmethod(printNumInstances)



>>> a, b = Spam(), Spam()
>>> a.printNumInstances()                    # Passes class to first argument
Number of instances: 2
>>> Spam.printNumInstances()                 # Also passes class to first argument
Number of instances: 2



class Spam:
    numInstances = 0                         # Trace class passed in
    def __init__(self):
        Spam.numInstances += 1
    def printNumInstances(cls):
        print("Number of instances:", cls.numInstances, cls)
    printNumInstances = classmethod(printNumInstances)

class Sub(Spam):
    def printNumInstances(cls):              # Override a class method
        print("Extra stuff...", cls)         # But call back to original
        Spam.printNumInstances()
    printNumInstances = classmethod(printNumInstances)

class Other(Spam): pass                      # Inherit class method verbatim



>>> x, y = Sub(), Spam()
>>> x.printNumInstances()                    # Call from subclass instance
Extra stuff... <class 'test.Sub'>
Number of instances: 2 <class 'test.Spam'>
>>> Sub.printNumInstances()                  # Call from subclass itself
Extra stuff... <class 'test.Sub'>
Number of instances: 2 <class 'test.Spam'>
>>> y.printNumInstances()
Number of instances: 2 <class 'test.Spam'>



>>> z = Other()
>>> z.printNumInstances()
Number of instances: 3 <class 'test.Other'>



class Spam:
    numInstances = 0
    def count(cls):                    # Per-class instance counters
        cls.numInstances += 1          # cls is lowest class above instance
    def __init__(self):
        self.count()                   # Passes self.__class__ to count
    count = classmethod(count)

class Sub(Spam):
    numInstances = 0
    def __init__(self):                # Redefines __init__
        Spam.__init__(self)

class Other(Spam):                     # Inherits __init__
    numInstances = 0

>>> x = Spam()
>>> y1, y2 = Sub(), Sub()
>>> z1, z2, z3 = Other(), Other(), Other()
>>> x.numInstances, y1.numInstances, z1.numInstances
(1, 2, 3)
>>> Spam.numInstances, Sub.numInstances, Other.numInstances
(1, 2, 3)



class C:
   @staticmethod                                 # Decoration syntax
   def meth():
       ...



class C:
   def meth():
       ...
   meth = staticmethod(meth)                     # Rebind name



class Spam:
    numInstances = 0
    def __init__(self):
        Spam.numInstances = Spam.numInstances + 1

    @staticmethod
    def printNumInstances():
        print("Number of instances created: ", Spam.numInstances)

a = Spam()
b = Spam()
c = Spam()
Spam.printNumInstances()      # Calls from both classes and instances work now!
a.printNumInstances()         # Both print "Number of instances created:  3"



class tracer:
    def __init__(self, func):
        self.calls = 0
        self.func  = func
    def __call__(self, *args):
        self.calls += 1
        print('call %s to %s' % (self.calls, self.func.__name__))
        self.func(*args)

@tracer                       # Same as spam = tracer(spam)
def spam(a, b, c):            # Wrap spam in a decorator object
    print(a, b, c)

spam(1, 2, 3)                 # Really calls the tracer wrapper object
spam('a', 'b', 'c')           # Invokes __call__ in class
spam(4, 5, 6)                 # __call__ adds logic and runs original object



def decorator(aClass): ...

@decorator
class C: ...



def decorator(aClass): ...

class C: ...
C = decorator(C)



def count(aClass):
    aClass.numInstances = 0
    return aClass                  # Return class itself, instead of a wrapper

@count
class Spam: ...                    # Same as Spam = count(Spam)

@count
class Sub(Spam): ...               # numInstances = 0 not needed here

@count
class Other(Spam): ...



class Meta(type):
    def __new__(meta, classname, supers, classdict): ...

class C(metaclass=Meta): ...



class C:
    __metaclass__ = Meta
    ...



>>> class X:
...     a = 1       # Class attribute
...
>>> I = X()
>>> I.a             # Inherited by instance
1
>>> X.a
1



>>> X.a = 2         # May change more than X
>>> I.a             # I changes too
2
>>> J = X()         # J inherits from X's runtime values
>>> J.a             # (but assigning to J.a changes a in J, not X or I)
2



class X: pass                       # Make a few attribute namespaces
class Y: pass

X.a = 1                             # Use class attributes as variables
X.b = 2                             # No instances anywhere to be found
X.c = 3
Y.a = X.a + X.b + X.c

for X.i in range(Y.a): print(X.i)   # Prints 0..5



class Record: pass
X = Record()
X.name = 'bob'
X.job  = 'Pizza maker'



>>> class C:
...     shared = []                 # Class attribute
...     def __init__(self):
...         self.perobj = []        # Instance attribute
...
>>> x = C()                         # Two instances
>>> y = C()                         # Implicitly share class attrs
>>> y.shared, y.perobj
([], [])

>>> x.shared.append('spam')         # Impacts y's view too!
>>> x.perobj.append('spam')         # Impacts x's data only
>>> x.shared, x.perobj
(['spam'], ['spam'])

>>> y.shared, y.perobj              # y sees change made through x
(['spam'], [])
>>> C.shared                        # Stored on class and shared
['spam']



x.shared.append('spam')    # Changes shared object attached to class in-place
x.shared = 'spam'          # Changed or creates instance attribute attached to x



class ListTree:
    def __str__(self): ...

class Super:
    def __str__(self): ...

class Sub(ListTree, Super):    # Get ListTree's __str__ by listing it first

x = Sub()                      # Inheritance searches ListTree before Super



class ListTree:
    def __str__(self): ...
    def other(self): ...

class Super:
    def __str__(self): ...
    def other(self): ...

class Sub(ListTree, Super):    # Get ListTree's __str__ by listing it first
    other = Super.other        # But explicitly pick Super's version of other
    def __init__(self):
        ...

x = Sub()                      # Inheritance searches Sub before ListTree/Super



class Sub(Super, ListTree):               # Get Super's other by order
    __str__ = Lister.__str__              # Explicitly pick Lister.__str__



def generate():                  # Fails prior to Python 2.2, works later
    class Spam:
        count = 1
        def method(self):        # Name Spam not visible:
            print(Spam.count)    # not local (def), global (module), built-in
    return Spam()

generate().method()

C:\python\examples> python nester.py
...error text omitted...
    Print(Spam.count)            # Not local (def), global (module), built-in
NameError: Spam



def generate():
    global Spam                 # Force Spam to module scope
    class Spam:
        count = 1
        def method(self):
            print(Spam.count)   # Works: in global (enclosing module)
    return Spam()

generate().method()             # Prints 1



def generate():
    return Spam()

class Spam:                    # Define at top level of module
    count = 1
    def method(self):
        print(Spam.count)      # Works: in global (enclosing module)

generate().method()



def generate():
    class Spam:
        count = 1
        def method(self):
            print(self.__class__.count)      # Works: qualify to get class
    return Spam()

generate().method()



### lab code



class Lunch:
    def __init__(self)               # Make/embed Customer and Employee
    def order(self, foodName)        # Start a Customer order simulation
    def result(self)                 # Ask the Customer what Food it has

class Customer:
    def __init__(self)                        # Initialize my food to None
    def placeOrder(self, foodName, employee)  # Place order with an Employee
    def printFood(self)                       # Print the name of my food

class Employee:
    def takeOrder(self, foodName)    # Return a Food, with requested name

class Food:
    def __init__(self, name)         # Store food name



% python
>>> from zoo import Cat, Hacker
>>> spot = Cat()
>>> spot.reply()                   # Animal.reply; calls Cat.speak
meow
>>> data = Hacker()                # Animal.reply; calls Primate.speak
>>> data.reply()
Hello world!



% python
>>> import parrot
>>> parrot.Scene().action()        # Activate nested objects
customer: "that's one ex-bird!"
clerk: "no it isn't..."
parrot: None

评论

此博客中的热门博文

OAuth 2教程

网格策略

apt-get详细使用