魔法方法、属性和迭代器

作者:追风剑情 发布于:2017-12-19 15:24 分类:Python

示例

# -*- coding: cp936 -*-
#魔法方法、属性和迭代器

class NewStyle(object):#继承object的类作为新式类
    pass

#这句声明之后定义的类都为新式类
__metaclass__ = type #使用新式类
#在Python3.0中都是新式类,不需要显示声明.

class FooBar:
    def __init__(self): #定义构造方法
        self.somevar = 42

class FooBar1:
    def __init__(self, value=42): #带形参的构造方法
        self.somevar = value

    def __del__(self): #对象被回收前会调用析构方法
        print '析构方法被调用'

class A:
    def hello(self):
        print "Hello, I'm A."

class B(A):
    def hello(self): #重定A类的hello方法
        print "Hello, I'm B."

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):
        #Bird.__init__(self) #调用父类的构造方法,这是旧版Python的写法
        super(SongBird, self).__init__() #新式类中可以这样写(推荐写法)
        #Python3.0中super函数可以不带任何参数。
        self.sound = 'Squawk!'
    def sing(self):
        print self.sound

#继承内建类型
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)

print '构造方法'
f = FooBar()
print f.somevar

f = FooBar1("This is a constructor argument")
print f.somevar

print '重写超类方法'
a = A()
b = B()
a.hello()
b.hello()

sb = SongBird()
sb.sing()
sb.eat()
sb.eat()

print '继承内建类型'
cl = CounterList(range(10))
print cl
cl.reverse()
print cl
del cl[3:6]
print cl
print cl[4] + cl[2] #通过索引访问会调用__getitem__()方法
print cl.counter

print '属性访问器方法'
#在新式类中推荐用访问器访问属性
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
    #property函数只在新式类中有用
    #property(fget、fset、fdel、doc) 可以用关键字参数赋值
    #fdel是一个用于删除特性的方法(它不要参数)
    #doc是一个文档字符串
    size = property(getSize, setSize) #创建属性size
    #size = property(getSize) #创建只读属性size

r = Rectangle()
r.width = 10
r.height = 5
print r.getSize()
r.setSize((150, 100))
print r.width
r.size = 200, 300
print r.width

print '静态方法和类成员方法'
#老版本Python实现方式
class MyClass:
    def smeth(): #静态方法没self参数
        print 'This is a static method'
    smeth = staticmethod(smeth) #手动包装(替换),现在smeth才是真正的静态方法。
    def cmeth(cls):#实例方法
        print 'This is a class method of ', cls
    cmeth = classmethod(cmeth) #手动包装(替换),现在cmeth才是真正的实例方法。

#Python2.4之后的实现方式
class MyClass1:
    @staticmethod
    def smeth():#静态方法
        print 'This is a static method'
    @classmethod
    def cmeth(cls):#实例方法
        print 'This is a class method of ', cls

MyClass1.smeth()
MyClass1.cmeth()

print '__getattr__、setattr__'
#__getattribute__(self, name)当特性name被访问时自动被调用(只能在新式类中使用)
#__getattr__(self, name)当特性name被访问且对象没有相应的特性时被自动调用。
#__setattr__(self, name, value)当试图给特性name赋值时会被自动调用。
#__delattr__(self, name)当试图删除特性name时被自动调用。
class Rectangle1:
    def __init__(self):
        self.width = 0
        self.height = 0
    def __setattr__(self, name, value):#给特性赋值时会被调用
        if name == 'size':
            self.width, self.height = value
        else:
            #__dict__方法被用来代替普通的特性赋值操作
            self.__dict__[name] = value #必须这样赋值,否则会陷入死循环
    #在旧式类中特性没有被找到时会被调用
    #在新式类中会拦截所有特性访问
    def __getattr__(self, name): 
        if name == 'size':
            return self.width, self.height
        else:
            raise AttributeError

print '迭代器__iter__'
#实现了__iter__方法的对象可迭代
#迭代器需要实现next方法
#在旧版本中要求迭代器实现next方法
#在Python3.0中要求迭代器实现__next__方法, 可以这样迭代next(it)
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;

#内建函数iter可以从可迭代的对象中获得迭代器
it = iter([1,2,3])
print it.next()
print it.next()

print '从迭代器得到序列'
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()
print list(ti)

print '生成器'
#生成器是一个包含yield关键字的函数
#yield语句意味着应该生成一个值
#return语句意味着生成器要停止执行(return语句只有在一个生成器中使用时才能进行无参数调用)
#创建一个生成器函数
def flatten(nested):
    for sublist in nested:
        for element in sublist:
            yield element
nested = [[1,2], [3,4], [5]]
#迭代nested
for num in flatten(nested):
    print num
#或者直接转成list输出
print list(flatten(nested))

print '生成器推导式'
g = ((i+2)**2 for i in range(2,27))
print g.next()
print sum(i**2 for i in range(10))#生成器推导式可以作为参数直接作用

print '递归迭代'
def flatten1(nested):
    try:
        #不要迭代类似字符串的对象
        try: nested + '' #通过检查可拼接性
        except TypeError: pass
        else: raise TypeError
        for sublist in nested:
            for element in flatten1(sublist):
                yield element
    except TypeError:
        yield nested

print list(flatten1(nested))

print '生成器方法' #Python2.5引入
print '生成器的send方法'
def repeater(value):
    while True:
        new = (yield value)#用括号闭合yield表达式
        if new is not None: value = new

r = repeater(42)
print r.next()
print r.send("Hello. world!")#给生成器发送参数
#生成器还有两个方法throw方法、close方法

#生成器在旧版Python中不可用
#下面用普通函数来实现生成器
def flatten2(nested):
    result = []
    try:
        try: nested + ''
        except TypeError: pass
        else: raise TypeError
        for sublist in nested:
            for element in flatten1(sublist):
                result.append(element)
    except TypeError:
        result.append(nested)
    return result

print list(flatten2(nested))

运行测试

11111.png

标签: Python

Powered by emlog  蜀ICP备18021003号-1   sitemap

川公网安备 51019002001593号