python进阶教程

1.迭代器
顾名思义,迭代器就是用于迭代操作(for 循环)的对象,它像列表一样可以迭代获取其中的每一个元素,任何实现了 next 方法的(对象)都可以称为迭代器。
它与列表的区别在于,构建迭代器的时候,不像列表把所有元素一次性加载到内存,而是以一种延迟计算(lazy evaluation)方式返回元素,这正是它的优点
话不多说,我们来看一个例子

class Fib(object):
     def __int__(_self,n):
           self.n = n 
           self.cur = 1
           self.prev = 0

    def __iter__(self):
          return self

    def __next__(self):
          if self.n > 0
             // python里面这种赋值超爽有木有
             self.cur,self.prev = self.cur + self.prev,self.cur 
             self.n -= 1
             return self.cur
          else:
             raise stopIteration()
f = Fib(10)
print([i for i in f])
#[1, 1, 2, 3, 5, 8, 13, 21, 34, 55]

上面以斐波那契数列为例来实现一个迭代器:
        

Fib类实现了魔术方法,在每回迭代的时候会调用next方法
2.魔术方法
咱们由浅入深举三个例子把

class student(object):
        def __init__(self, name):
              self.name = name
        def __call__(self):
              print 'my name is {0}'.format(self.name)
aa = student('aa')
aa()  会调用call()方法  
output: 'My name is aa'

class A():
    def __init__(self):
        print "call __init__"
        self.value = [1,2,3,4,5,6]

    def __len__(self):
        print "call __len__"
        return len(self.value)

    def __getitem__(self, index):
        print "call __getitem__"
        return self.value[index]
aa = A()
print (len(aa))  ========   6
print aa[2]   ======== 3   这里调用了getItem方法  取下标为2的值

看一个稍微复杂一点的

class ListMetaclass(type):
        def __new__(cls, name, bases, attrs):
            attrs['add'] = lambda self, value: self.append(value)
            return type.__new__(cls, name, bases, attrs)
   

class MyList(list, metaclass=ListMetaclass):
           pass

ld = MyList()
ld.add('ni')
ld ========= ['ni']

这个涉及到了元类,跟js里面的原型有相似之处,但比原型好理解些。
简单解释一下:
Mylist继承了list是一个列表类,具有append方法,然后她后面又跟了个metaclass也就是元类,所有继承该元类的类都拥有add方法,是一个lambda表达式的函数self.append(value),所以知道为什么能有append了吧。
今天不深究,下回有时间我会搞一期元类和魔术方法的专题。

3.生成器
生成器算得上是Python语言中最吸引人的特性之一,生成器其实是一种特殊的迭代器,不过这种迭代器更加优雅。它不需要再像上面的类一样写iter()和next()方法了,只需要一个yiled关键字。

from itertools import islice
def fib():
    prev, curr = 0, 1
    while True:
        yield curr
        prev, curr = curr, curr + prev
 
>>> f = fib()
>>> list(islice(f, 0, 10))
[1, 1, 2, 3, 5, 8, 13, 21, 34, 55]

itertools是一个很有用的工具类,大家自行google
生成器都有一个send方法

def count(n):
    x = 0
    while x < n:
        value = yield x
        if value is not None:
            print 'Received value: %s' %value
        x += 1

gen = count(5)
print  (gen.__next__())  # print 0
print (gen.send('Hello') ) # Received value: Hello, then print 1

注意用的python3版本的要调用next方法 打印需要加括号
来一个综合一点的例子

def consumer():
    last = ''
    while True:
        //receival是生成器send过来的值
        receival = yield last
        if receival is not None:
            print ('Consume %s' % receival)
            last = receival


def producer(gen, n):
    //这一步启动生成器很关键
    gen.__next__()
    x = 0
    while x < n:
        x += 1
        print ('Produce %s' % x)
        print (gen.send(x))

    gen.close()

gen = consumer()
producer(gen, 5)
output:
Produce 1
Consume 1
1
Produce 2
Consume 2
2
...

结束循环时,用生成器的close方法关闭她。

4.装饰器
搞过java开发的人应该知道,aop面向切面织入方法。玩过angular的也应该知道,依赖注入也是装饰器的一种,很幸运2者我都接触过。

import time
def performance(f):
    @functools.wraps(decorated)
    def fn(*args, **kw):
        t1 = time.time()
        r = f(*args, **kw)
        t2 = time.time()
        print 'call %s() in %fs' % (f.__name__, (t2 - t1))
        return r
    return fn

@performance
def factorial(n):
    return reduce(lambda x,y: x*y, range(1, n+1))
print factorial(10)

说明2点,@functools.wraps(decorated)是保证factorial函数被装饰后名字不变,
另外reduce在python3中需要引入。
下面介绍一下装饰器传参的用法

import json
import functools

def json_output(indent=None, sort_keys=False):
    //想想这里为什么会多一层函数 以前的外层装饰器参数是被修饰的函数
    def actual_decorator(func):
        @functools.wraps(func)
        def inner(*args, **kwargs):
            result = func(*args, **kwargs)
            return json.dumps(result, indent=indent, sort_keys=sort_keys)

        return inner

    return actual_decorator

@json_output(18, sort_keys=True)
def f():
    return {'status': 'done','aa':'bb'}
print (f())
output:
 {
                  "aa":"bb",
                  "status":"done"
}

写到这里chrome居然崩溃了。。。
上面的意思是序列化一个json,缩进18,按键排序。
好了,今天说了iterator,generator,decrator,还有魔术方法,下回会跟大家分享爬虫或者python实用库,尽情期待吧,如果觉得写得比较有条理,点波关注哟。

你可能感兴趣的:(python进阶教程)