Python 进阶

1 迭代器、生成表达式和生成器

1.1 迭代器(iterators)

迭代器对象拥有个next方法用来表达下一个对象,并且如果导到了最后一个,将会抛出一个StopIteration的异常


In [1]:
num=[1,2,3]
iter(num)


Out[1]:
<listiterator at 0x10470fa10>

In [3]:
num.__iter__()


Out[3]:
<listiterator at 0x1047270d0>

In [4]:
num.__reversed__()


Out[4]:
<listreverseiterator at 0x10470fe90>

In [5]:
it = iter(num)
print it.next()
print it.next()
print it.next()
print it.next()


1
2
3
---------------------------------------------------------------------------
StopIteration                             Traceback (most recent call last)
<ipython-input-5-089dd208f5c3> in <module>()
      3 print it.next()
      4 print it.next()
----> 5 print it.next()

StopIteration: 

通过for语句可以来进行迭代整个迭代器的对象。

1.2 生成表达式(generate expression)

生成迭代器的另外一种方法是通过生成表达式


In [6]:
(i for i in num)


Out[6]:
<generator object <genexpr> at 0x1047d85a0>

In [7]:
[i for i in num]


Out[7]:
[1, 2, 3]

不仅仅可以生成列表,还有生成集合(set)或者是字典,只要在外边添加一组{}即可


In [14]:
{i for i in range(3)}


Out[14]:
{0, 1, 2}

In [12]:
{i:i**2 for i in range(3)}


Out[12]:
{0: 0, 1: 1, 2: 4}

1.3 生成器(generator)

生成器函数通过yield关键字来处理迭代器的生成,每当next函数被调用,将会执行一次yield操作,直至yield操作全部完成。


In [15]:
def f():
    yield 1
    yield 2
f()


Out[15]:
<generator object f at 0x1047d8730>

In [17]:
gen=f()
gen.next()


Out[17]:
1

In [18]:
gen.next()


Out[18]:
2

In [19]:
gen.next()


---------------------------------------------------------------------------
StopIteration                             Traceback (most recent call last)
<ipython-input-19-b2c61ce5e131> in <module>()
----> 1 gen.next()

StopIteration: 

再看一个生成器的实例,观察该函数如何被调用的


In [21]:
def f():
    print '---first---'
    yield 3
    print '---middle---'
    yield 4
    print '---finish---'
gen=f()
gen.next()


---first---
Out[21]:
3

In [22]:
gen.next()


---middle---
Out[22]:
4

In [23]:
gen.next()


---finish---
---------------------------------------------------------------------------
StopIteration                             Traceback (most recent call last)
<ipython-input-23-b2c61ce5e131> in <module>()
----> 1 gen.next()

StopIteration: 

gen=f()处,函数并没有被调用,而是在第一次调用next()函数的时候,执行print '---first---'语句,当执行最后的next()语句的时候执行了最后的print '---finish---'语句。

2 装饰器

由于在Python中函数也是一种对象,所以可以将其进行传递,通过装饰器可以修改一个函数的行为。


In [26]:
def simple_decorator(f):
    print 'decorator'
    return f
@simple_decorator
def f():
    print 'origin function'
f()


decorator
origin function

需要装饰的函数会有一些参数,可以使用通用的参数形式*args,**kw来适应所有情况


In [30]:
def para_decorator(f):
    def _wrapper(*args,**kw):
        print 'para decorator'
        return f(*args,**kw)
    return _wrapper
@para_decorator
def f(name):
    print 'name is {}.'.format(name)
f('gaufung')


para decorator
name is gaufung.

有时装饰器函数也接受参数,则装饰器函数需要进一步封装。


In [31]:
def paras_decorator(value):
    def para_decorator(f):
        def _wrapper(*args,**kw):
            print value
            return f(*args,**kw)
        return _wrapper
    return para_decorator
@paras_decorator('zhangsan')
def f(name):
    print 'name is {}.'.format(name)
f('gaufung')


zhangsan
name is gaufung.

通常通过装饰器处理的函数,会改变整个函数的签名,为了不改变被装饰函数的签名,需要进一步处理。


In [37]:
import functools
def decorator_f(f):
    @functools.wraps(f)
    def _wrapper(*args,**kw):
        return f(*args,**kw)
    return _wrapper
@decorator_f
def f():
    pass

2.1 标准库中的装饰器

  • classmethod

方法中如果标记为 @classmethod 那么该函数将被类调用,而不是被类的实例对象调用。该方法参数中不用self,而是cls


In [55]:
class A(object):
    def __init__(self,args):
        self._args = args
    @classmethod
    def say(cls):
        print 'say hello'
A.say()


say hello
  • staticmethod

可以通过类所在的命名空间方位该函数,通常来讲用来该函数的前缀为_,用来表明该函数与这个类相关,虽然这个函数不是必须的。


In [53]:
class B(object):
    def __init__(self,arg):
        self._args = arg
    @staticmethod
    def speak():
        print 'speak hello'
B.speak()


speak hello
  • property

通过property的装饰器,可以使用简介的set和get操作,方便使用。

2.2 添加deprecate信息

如果一个函数如果已经被丢弃,当用户在第一次使用该函数的时候,输出相关信息。

  • 类实现

In [58]:
class deprecated(object):
    def __call__(self,func):
        self.func = func
        self.count = 0
        return self._wrapper
    def _wrapper(self,*args,**kw):
        self.count += 1
        if self.count == 1:
            print self.func.__name__,'is deprecated.'
        return self.func(*args,**kw)
@deprecated()
def f():
    pass
f()


f is deprecated.
  • 函数实现

In [59]:
def deprecated(func):
    count = [0]
    def _wrapper(*args,**kw):
        count[0] += 1
        if count[0] == 1:
            print func.__name__,'is deprecated'
        return func(*args,**kw)
    return _wrapper
@deprecated
def f():
    pass
f()


f is deprecated

In [ ]: