Python基础教程之魔法方法、属性和迭代器实例代码

发布时间:2020-01-29编辑:脚本学堂
本文介绍了Python基础教程之魔法方法、属性和迭代器的练习实例代码,需要的朋友参考下。

python基础教程之魔法方法、属性和迭代器实例代码

相关介绍文章,请参考:python基本教程之魔法方法、属性和迭代器

以下是实例代码:
 

复制代码 代码示例:
#魔法方法, 属性 和 迭代器 
D:>python 
Python 2.7.5 (default, May 15 2013, 22:43:36) [MSC v.1500 32 bit (Intel)] on win32 
Type "help", "copyright", "credits" or "license" for more information. 
#9.1准备工作 
>>> __metaclass__=type 
>>> class NewStyle(object): 
...     pass # more_code_here 
... 
>>> class OldStyle: 
...     pass # more_code_here 
... 
#9.2 构造器(constructor) 
>>> class FooBar: 
...     def __init__(self): 
...             self.somevar = 42 
... 
>>> f = FooBar() 
>>> f.somevar 
42 
>>> 
>>> class FooBar: 
...     def __init__(self, value=42): 
...             self.somevar = value 
... 
>>> f = FooBar('This is a constructor argument') 
>>> f.somevar 
'This is a constructor argument' 
 
#9.2.1 重写一般方法和特殊的constructor 
>>> class A: 
...     def hello(self): 
...             print "Hello, I'm A." 
... 
>>> class B(A): 
...     pass 
... 
>>> a = A() 
>>> b = B() 
>>> a.hello() 
Hello, I'm A. 
>>> b.hello() 
Hello, I'm A. 
>>> 
>>> class B(A): 
...     def hello(self): 
...             print "Hello, I'm B" 
... 
>>> b = B() 
>>> b.hello() 
Hello, I'm B 
 
>>> class Bird: 
...     def __init__(self): 
...             self.hungry = True 
...     def eat(self): 
...             if self.hungry: 
...                     print 'Aaaah...' 
...             else: 
...                     print 'No, thanks!' 
... 
>>> class Bird: 
...     def __init__(self): 
...             self.hungry = True 
...     def eat(self): 
...             if self.hungry: 
...                     print 'Aaaah...' 
...                     self.hungry = False 
...             else: 
...                     print 'No, thanks!' 
... 
>>> b = Bird() 
>>> b.eat() 
Aaaah... 
>>> b.eat() 
No, thanks! 
>>> class SongBird(Bird): 
...     def __init__(self): 
...             self.sound = 'Squlinuxjishu/13830.html target=_blank class=infotextkey>awk!' 
...     def sing(self): 
...             print self.sound 
... 
>>> sb = SongBird() 
>>> sb.sing() 
Squawk! 
>>> sb.eat() 
Traceback (most recent call last): 
  File "<stdin>", line 1, in <module> 
  File "<stdin>", line 5, in eat 
AttributeError: 'SongBird' object has no attribute 'hungry' 
>>> 
#9.2 调用未绑定的超类构造器 
>>> class SongBird(Bird): 
...     def __init__(self): 
...             Bird.__init__(self) 
...             self.sound='Squark!' 
...     def sing(self): 
...             print self.sound 
... 
>>> sb = SongBird() 
>>> sb.sing() 
Squark! 
>>> sb.eat() 
Aaaah... 
>>> sb.eat() 
No, thanks! 
 
#9.2 使用super函数 
#conding = utf-8 
__metaclass__ = type # super() only works in new style classes 
class Bird: 
    def __init__(self): 
        self.hungry = True 
    def eat(self): 
        if self.hungry: 
            print 'Aaaah...' 
            self.hungry = False 
        else: 
            print 'No, thanks!' 
 
class SongBird(Bird): 
    def __init__(self): 
        super(SongBird, self).__init__() # 在Python 3.0 中, super函数可以不用任何参数进行调用, 功能依然具有"魔力" 
        self.sound = 'Squark!' 
    def sing(self): 
        print self.sound 
         
sb = SongBird() 
sb.sing() 
sb.eat() 
sb.eat() 
 
#python tt.py 
#Squark! 
#Aaaah... 
#No, thanks! 
 
#9.3 成员访问 
#9.3.1 基本的序列和映射规则 
#coding = utf-8 
def checkIndex(key): 
    """
    所给的键时能接受的索引吗?
    为了能被接受, 键应该是一个非负的整数. 如果它不是一个整数, 会引发TypeError; 如果它是负数, 则会引发IndexError(因为序列是无限长的)
    """ 
    if not isinstance(key, (int, long)): raise TypeError 
    if key<0: raise IndexError 
     
class ArithmeticSequence: 
    def __init__(self, start=0, step=1): 
        """
        初始化算术序列
        起始值:序列中的第一个值
        步长: 两个相邻值之间的差别
        改变: 用户修改的值的字典
        """ 
         
        self.start = start      #保存开始值 
        self.step = step        #保存步长值 
        self.changed = {}       #没有项被修改 
 
    def __getitem__(self, key): 
        """
        Get an item from the arithmetic sequence.
        """ 
        checkIndex(key) 
        try: return self.changed[key]           #修改了吗? 
        except KeyError:                        #否则... 
            return self.start + key*self.step   #...计算值 
             
    def __setitem__(self, key,  value): 
        """
        修改算术序列中的一个项
        """ 
        checkIndex(key) 
        self.changed[key]=value # 保存更改后的值 
         
s = ArithmeticSequence(1, 2) 
print s[0] 
print s[1] 
print s[2] 
print s[3] 
print s[4] 
 
s[4]=2 
print s[4] 
 
print s[5] 
 
#del s[4] 
#Traceback (most recent call last): 
#  File "tta.py", line 51, in <module> 
#    del s[4] 
#AttributeError: ArithmeticSequence instance has no attribute '__delitem__' 
 
#print s["four"] 
#Traceback (most recent call last): 
#  File "tta.py", line 57, in <module> 
#    s["four"] 
#  File "tta.py", line 27, in __getitem__ 
#    checkIndex(key) 
#  File "tta.py", line 7, in checkIndex 
#    if not isinstance(key, (int, long)): raise TypeError 
#TypeError 
 
#print s[-42] 
#Traceback (most recent call last): 
#  File "tta.py", line 67, in <module> 
#    print s[-42] 
#  File "tta.py", line 27, in __getitem__ 
#    checkIndex(key) 
#  File "tta.py", line 8, in checkIndex 
#    if key<0: raise IndexError 
#IndexError 
 
#9.3.2 对列表, 字典和字符串进行子类化 
 
>>> class CounterList(list): 
...     def __init__(self, *args): 
...             super(CounterList, self).__init__(*args) 
...             self.counter = 0 
...     def __getitem__(self, index): 
...             self.counter += 1 
...             return super(CounterList, self).__getitem__(index) 
... 
>>> c1 = CounterList(range(10)) 
>>> c1 
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 
>>> c1.reverse() 
>>> c1 
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0] 
>>> del c1[3:6] 
>>> c1 
[9, 8, 7, 3, 2, 1, 0] 
>>> c1.counter 

>>> c1[4] + c1[2] 

>>> c1.counter 

 
#9.4更多魔力 http://www.python.org/doc/ref/specialnames.html 
 
#9.5 属性 
>>> class Rectangle: 
...     def __init__(self): 
...             self.width=0 
...             self.height=0 
...     def setSize(self, size): 
...             self.width, self.height = size 
...     def getSize(self): 
...             return self.width, self.height 
... 
>>> r = Rectangle() 
>>> r.width=10 
>>> r.height=5 
>>> r.getSize() 
(10, 5) 
>>> r.setSize(150, 100) 
Traceback (most recent call last): 
  File "<stdin>", line 1, in <module> 
TypeError: setSize() takes exactly 2 arguments (3 given) 
>>> r.setSize((150, 100)) 
>>> r.width 
150 
 
#9.5.1 property 函数 
#幸好, Python能隐藏访问器方法, 让所有特性看起来一样. 这些通过访问器定义的特性被称为属性 
__metaclass__ = type 
class Rectangle: 
    def __init__(self): 
        self.width = 0 
        self.height = 0 
    def setSize(self, size): 
        self.width, self.height = size 
    def getSize(self): 
        return self.width, self.height 
    size = property(getSize, setSize) 
     
r = Rectangle() 
r.width = 10 
r.height = 5 
print r.size 
r.size = 150, 100 
print r.width 
 
#python my.py 
#(10, 5) 
#150 
 
 
#9.5.2 静态方法和类成员方法 
__metaclass__ = type 
class MyClass: 
    def smeth(): 
        print 'This is a static method' 
    smeth = staticmethod(smeth) 
         
    def cmeth(cls): 
        print 'This is a class method of', cls 
    cmeth = classmethod(cmeth) 
         
MyClass.smeth() 
MyClass.cmeth() 
 
#python ttb.py 
#This is a static method 
#This is a class method of <class '__main__.MyClass'> 
 
__metaclass__ = type 
class MyClass: 
    @staticmethod 
    def smeth(): 
        print 'This is a static method' 
        
    @classmethod 
    def cmeth(cls): 
        print 'This is a class method of', cls 
         
MyClass.smeth() 
MyClass.cmeth() 
 
#python ttc.py 
#This is a static method 
#This is a class method of <class '__main__.MyClass'> 
 
#9.5.3 __getattr__, __setattr__, __delattr__  
#__getattribute__(self, name) 
#__getattr__(self, name) 
#__setattr__(self, name) 
#__delattr__(self, name) 
 
 
class Rectangle: 
    def __init__(self): 
        self.width=0 
        self.height=0 
         
    def __setattr__(self, name,  value): 
        if name == 'size': 
            self.width, self.height = size 
        else: 
            self.__dict__[name] = value 
     
    def __getattr__(self, name): 
        if name == 'size': 
            return self.width, self.height 
        else: 
            raise AttributeError 
             
             
 
#9.6 迭代器 
#9.6.1 迭代器规则 
#__iter__方法返回一个迭代器(iterator), 所谓的迭代器就是具有next方法的对象. 在调用next方法时, 迭代器会返回它的下一个值. 
#如果next方法被调用, 但迭代器没有值可以返回, 就会引发一个StopIteration异常 
 
>>> class Fibs: 
...     def __init__(self): 
...             self.a = 0 
...             self.b = 1 
...     def next(self): 
...             self.a, self.b = self.b, self.a+self.b 
...             return self.a 
...     def __iter__(self): 
...             return self 
... 
>>> fibs = Fibs() 
>>> for f in fibs: 
...     if f > 1000: 
...             print f 
...             break 
... 
1597 
 
#内建函数iter可以从可迭代的对象中获得迭代器 
>>> it = iter([1,2,3]) 
>>> it.next() 

>>> it.next() 

 
#9.6.2 从迭代器得到序列 
>>> class TestIterator: 
...     value = 0 
...     def next(self): 
...             self.value += 1 
...             if self.value > 10: raise StopIteration 
...             return self.value 
...     def __iter__(self): 
...             return self 
... 
>>> ti = TestIterator() 
>>> list(ti) 
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10] 
 
#9.7 生成器 
#9.7.1 创建生成器 
>>> nested = [[1,2],[3,4],[5]] 
>>> def flatten(nested): 
...     for sublist in nested: 
...             for element in sublist: 
...                     yield element 
... 
>>> for num in flatten(nested): 
...     print num 
... 





>>> list(flatten(nested)) 
[1, 2, 3, 4, 5] 
 
 
>>> g = ((i+2)**2 for i in range(2,27)) 
>>> g.next() 
16 
>>> sum(i**2 for i in range(10)) 
285 
>>> sum(i for i in range(1,100)) 
4950 
>>> sum(i for i in range(1,101)) 
5050 
>>> 
 
#9.7.2 递归生成器 
def flatten(nested): 
    try: 
        for sublist in nested: 
            for element in flatten(sublist): 
                yield element 
    except TypeError: 
        yield nested 
 
print list(flatten([[[1],2],3,4,[5,[6,7]],8])) 
 
print list(flatten([[1,2],[3,4],[5]])) 
 
#python tte.py 
#[1, 2, 3, 4, 5, 6, 7, 8] 
#[1, 2, 3, 4, 5] 
 
 
def flatten(nested): 
    try: 
        #不要迭代类似字符串的对象 
        try: nested + '' 
        except TypeError: pass 
        else: raise TypeError 
        for sublist in nested: 
            for element in flatten(sublist): 
                yield element 
    except TypeError: 
        yield nested 
             
print list(flatten(['foo', ['bar', ['baz']]])) 
 
print list(flatten([[[1],2],3,4,[5,[6,7]],8])) 
 
print list(flatten([[1,2],[3,4],[5]])) 
 
#['foo', 'bar', 'baz'] 
#[1, 2, 3, 4, 5, 6, 7, 8] 
#[1, 2, 3, 4, 5] 
 
#9.7.3 通用生成器 
 
>>> def simple_generator(): 
...     yield 1 
... 
>>> simple_generator() 
<generator object simple_generator at 0x00BBD418> 
>>> simple_generator 
<function simple_generator at 0x00BB2870> 
 
#9.7.4 生成器方法 
def repeater(value): 
    while True: 
        new = (yield value) 
        if new is not None: value = new 
         
r = repeater(42) 
print r.next() 
print r.send("Hello, world!") 
 
#42 
#Hello, world! 
 
#9.7.5 模拟生成器 
def flatten(nested): 
    result = [] 
    try: 
        # don't iterate on strings 
        try: nested + '' 
        except TypeError: pass 
        else: raise TypeError 
        for sublist in nested: 
            for element in flatten(sublist): 
                result.append(element) 
    except TypeError: 
        result.append(nested) 
    return result 
     
print list(flatten(['foo', ['bar', ['baz']]])) 
 
print list(flatten([[[1],2],3,4,[5,[6,7]],8])) 
 
print list(flatten([[1,2],[3,4],[5]])) 
 
#['foo', 'bar', 'baz'] 
#[1, 2, 3, 4, 5, 6, 7, 8] 
#[1, 2, 3, 4, 5] 
 
#9.8 八皇后问题 
#9.8.1 生成器和回溯 
#9.8.2 问题 
#9.8.3 状态表示 
#9.8.4 寻找冲突 
#9.8.5 基本情况 
#9.8.6 需要递归的情况 
#9.8.7 助手函数 
 
# coding = utf-8 
#state[0]==3, 表示在第1行的皇后是在第4列 
#参数nextX代表下一个皇后的水平位置(x坐标或列), nextY代表垂直位置(y坐标或行) 
def conflict(state, nextX): 
    nextY = len(state) 
    for i in range(nextY): 
        # 如果下一个皇后和正在被考虑的当前皇后的水平距离为0(列相同)或者等于垂直距离(在一条对角线上)就返回True,否则就返回False 
        if abs(state[i]-nextX) in (0, nextY-i): 
            return True 
    return False 
 
def queens(num, state): 
    if len(state) == num - 1: 
        for pos in range(num): 
            if not conflict(state, pos): 
                yield pos 
                 
print list(queens(4, (1,3,0))) 
#[2] 
 
def queens(num, state): 
    if len(state) == num - 1: 
        for pos in range(num): 
            if not conflict(state, pos): 
                yield pos 
    else: 
        for pos in range(num): 
            if not conflict(state, pos): 
                for result in queens(num, state + (pos,)): 
                    yield(pos,) + result 
                     
def queens(num=8, state=()): 
    for pos in range(num): 
        if not conflict(state, pos): 
            if len(state) == num - 1: 
                yield(pos,) 
            else: 
                for result in queens(num, state + (pos,)): 
                    yield (pos,) + result 
                     
print list(queens(3)) 
#[] 
 
print list(queens(4)) 
#[(1, 3, 0, 2), (2, 0, 3, 1)] 
 
for solution in queens(8): 
    print solution 
    #[(1, 3, 0, 2), (2, 0, 3, 1)] 
#(0, 4, 7, 5, 2, 6, 1, 3) 
#(0, 5, 7, 2, 6, 3, 1, 4) 
#(0, 6, 3, 5, 7, 1, 4, 2) 
#... 
#(7, 3, 0, 2, 5, 1, 6, 4) 
 
     
print len(list(queens(8))) 
#92 
def prettyprint(solution): 
    def line(pos, length=len(solution)): 
        return '. '*(pos) + 'X ' + '. '*(length-pos-1) 
    for pos in solution: 
        print line(pos) 
 
import random 
prettyprint(random.choice(list(queens(8)))) 
#. . X . . . . . 
#. . . . . X . . 
#. X . . . . . . 
#. . . . . . X . 
#X . . . . . . . 
#. . . X . . . . 
#. . . . . . . X 
#. . . . X . . . 
 
print '' 
 
prettyprint(random.choice(list(queens(4)))) 
#. . X . 
#X . . . 
#. . . X 
#. X . . 
 
#9.9 小结 
#旧式类和新式类  魔法方法  构造器  重写  序列和映射  迭代器  生成器 八皇后问题 
#新函数 
#iter(obj)      从一个可迭代对象得到迭代器 
#property(fget, fset, fdel, doc)        返回一个属性, 所有的参数都是可选的 
#super(class, obj)      返回一个类的超类的绑定实例