Python构造函数,迭代器

构造函数

1.  一个对象被创建之后立刻调用构造函数

__function__这种形式的函数会在特殊情况下被调用,如:__init__

两行变一行:
f = FooBar()
f.init()  #这一行就不用调用了

使用__init__:f = FooBar() 即可

# -*- coding: utf-8 -*-
class FooBar:
    def __init__(self):
        self.var = 42
f = FooBar()
print f.var


class FooBar:
    def __init__(self,value = 42): # 赋予参数默认值
        self.var = value
f = FooBar('That is it') # 构造方法有参数
print f.var
f = FooBar() # 构造方法有参数
print f.var


2. 继承重写构造方法

如果重写超类的构造方法,那么需要调用超类的构造方法,否则可能会出错:

# -*- coding: utf-8 -*-
class Bird:
    def __init__(self):
        self.hungry = True
    def eat(self):
        if self.hungry:
            print 'Aaah...'
            self.hungry = False # 调用了构造方法中的值
        else:
            print 'No,thanks'

b = Bird()
b.eat()
b.eat()

class SongBird(Bird):# 继承超类
    def __init__(self):
        self.sound = 'Squawk!' # 没有 hungry 特性
    def sing(self):
        print self.sound
sb = SongBird()
sb.sing()
sb.eat() # 超类有的子类也有

调用超类构造方法解决上述问题:super函数 / 调用超类构造方法未绑定版本

class SongBird(Bird):# 继承超类
    def __init__(self):
        
        super(SongBird,self).__init__() # 使用类+对象作为参数
        #Bird.__init__(self) # 使用类方法,实例没有被绑定
        
        self.sound = 'Squawk!'
    def sing(self):
        print self.sound

未绑定方法:没有实例被绑定,可以自由的提供所需要的self 参数


*3. 引申出模仿方法

创建类似序列的对象:

# -*- coding: utf-8 -*-
def checkIndex(key): # 检查索引是否合法
    if not isinstance(key,(int,long)):raise TypeError
    if key<0:raise IndexError
class sequence:
    def __init__(self, start=0, step=1):# 初始化参数防止出事
        self.start = start
        self.step = step
        self.changed = {}
    def __getitem__(self,key): #生成了一个无限长的序列
        checkIndex(key)
        try:# 异常捕捉的妙用: 改变了值则返回改变的值,没有改变值则返回设定值
            return self.changed[key] # self.changed = {}初始化默认为空 
        except KeyError:#用户没有给序列设定值
            return self.start + self.step * key 

    def __setitem__(self, key, value): #给用户用于修改的
        checkIndex(key)
        self.changed[key] = value
s=sequence(1,2)
print s[4] # 调用方法__getitem__
s[4]=2
print s[4],s[5]
print s['four']
子类化列表,字符串,字典:

# -*- coding: utf-8 -*-
class CounterList(list): # 继承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)
cl = CounterList(range(10))
print cl #没有重写任何方法,超类的都可以用
print cl.counter
cl[4]+cl[2] #访问了两次
print cl.counter


迭代器

__iter__方法:迭代器规则的基础,返回一个迭代器

for 循环除了对序列,字典迭代,可以对实现了__iter__方法(返回一个iterator)的对象迭代(使用迭代器的原因:更通用,简单)。

比如需要计算值:迭代器一个个算,列表一次获取所有值,若值很多则很占内存。

使用迭代器实现斐波那契:

# -*- coding: utf-8 -*-
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): # 放到会在for循环中使用的对象中
        return self

fibs = Fibs()
for f in fibs: # __iter__
    if f>1000:
        print f
        break
生成一个10以内的迭代器:
# -*- coding: utf-8 -*-
class Iteration:
    value = 0
    def next(self):
        self.value += 1
        if self.value>10: raise StopIteration
        return self.value
    def __iter__(self):
        return self
ti = Iteration()
for t in ti:
    print t


1. 生成器

包含 yield 语句的函数:生成器

生成器与return不同,生成一个值就pause,下次调用时继续函数,而不会像return 一样终止函数。

所以在处理:任意层嵌套(例如树形结构),并不知道到底有多少层嵌套——需要递归+生成器:

# -*- coding: utf-8 -*        
def flatten(nested):
    try: #对于一个任意的树形结构,至少应该有两层for循环:两种情况
        for sublist in nested: #基本情况:展开一个元素——TypeError
            for element in flatten(sublist): # 需要递归的情况:展开可迭代对象
                print element
                yield element
                #return element 找到第一个元素的时候就返回了,无法遍历后面的元素
    except TypeError: # 排除TypeError: 'int' object is not iterable, 基本情况:展开一个元素
        yield nested
        #return nested
print list(flatten([[[1],2],3,4,[5,[6,7]],8]))
遇到字符串怎么办,因为对字符串进行迭代会导致无穷递归:

def flatten(nested):
    try:
        try:nested + '' # 检验是否是字符串
        except TypeError:pass # 不是则进行下一步
        else:raise TypeError # 是字符串就异常终止程序
        for sublist in nested: 
            for element in flatten(sublist): 
                print element
                yield element
    except TypeError: 
        yield nested

普通函数实现上述:

def flatten(nested):
    result = []
    try:
        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

一层循环实现:(很局限,首先需要知道每一个元素可能的类型)

# -*- coding: utf-8 -*
listx = []
def flatten(nested):
    #listx = [] 注意位置!在后面调用flatten的时候又会产生一个新的listx
    for i in nested:
        if type(i) is not list:
            listx.append(i)
        else:
            flatten(i)
    return listx
print flatten([[[1],2],3,4,[5,[6,7]],8])
这段代码就要求提前想好 i 可能的类型,而之前的两段代码是直接创造一个可能会出错(如果不是集合类型,而像数字之类的是不能迭代的)的代码,之后的事全交给异常处理来管TypeError,不用预知每个元素可能是什么类型。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值