当前位置: 移动技术网 > IT编程>脚本编程>Python > 【Py3】模块和语法(1)

【Py3】模块和语法(1)

2020年07月30日  | 移动技术网IT编程  | 我要评论
python3语法和模块,包块迭代器,生成器和装饰器等

collections模块

Python内置标准库中的collections提供了一些很实用的数据结构

  • namedtuple:用于创建元祖子类的工厂函数(factory function),可以通过属性名访问元索引
  • deque:双端队列
  • ChainMap:类似字典类,用于创建多个映射的单一视图
  • Counter:字典子类,对可哈希对象进行计数
  • OrderedDict:字典子类,可以保存元素的添加顺序
  • defaultdict:字典子类,可以通过调用用户自定义的工厂函数来设置缺失值

迭代器

迭代器是实现了迭代协议的容器对象,基于以下两种方法

  • __next__:返回容器的下一个元素
  • __iter__:返回迭代器本身

当迭代完所有序列时,会发生StopIteration异常,可以通过捕获该异常停止迭代. 实现自定义迭代器,可以编写一个具有__next__方法的类,只要该类提供返回迭代器实例的__iter__的特殊方法

class MyIter:
    def __init__(self, step):
        self.step=step
    def __next__(self):
        if self.step<=0: raise StopIteration
        self.step-=1
        return self.step
    def __iter__(self):
        return self
    
def main():
    for element in MyIter(5): print(element, end=' ')
    
if __name__ == "__main__":
    main()

生成器

基于yield语句,生成器可以暂停函数并返回一个中间结果,该函数可以保存执行上下文(context),支持恢复现场.
使用yield语句生成Fibonacci数列

def fibonacci():
    a, b=0, 1
    while True:
        yield b
        a, b = b, b+a
    
def main():
    fib=fibonacci()
    for i in range(10): print(next(fib), end=' ')
    
if __name__ == "__main__":
    main()

在数据序列转换算法中,生成器可以降低算法的时间复杂度,将每个序列看做一个iterator,然后将其合并为一个高阶函数,形成处理链.

def power(values):
    for value in values:
        print('powering :{}'.format(value))
        yield value

def adder(values):
    for value in values:
        print('adding :{}'.format(value))
        if value & 0x01: yield value+1
        else: yield value

def main():
    e=[i for i in range(1, 20, 3)]
    ans=adder(power(e))
    for _ in range(3): next(ans)
    
if __name__ == "__main__":
    main()

生成器可以通过next函数与调用的代码进行交互,值可以通过send方法传递. 这种特性是Python中协程和异步并发的基础.

def robot():
    print('tell me your problem')
    while True:
        ans=(yield) # yield作为表达式使用
        if ans:
            if ans.endswith('?'): print("ROBOT: what's your problem?")
            elif 'good' in ans: print('ROBOT: that is good')
            elif 'bad' in ans: print('ROBOT: No more bad, bro')
                                        
def main():
    rob=robot()
    next(rob)
    rob.send('I feel bad?')
    rob.send('I feel good')
    rob.send('I amd bad')
                                        
if __name__ =='__main__':
    main()

装饰器

装饰器的作用是函数包装,实现函数的功能加强,避免函数的重复定义.

class Decorators:
    @staticmethod
    def foo1(): print('static method')
    @classmethod
    def foo2(): print('class method')

装饰器通常是一个命名对象,在被装饰函数调用时接受单一参数,并返回一个可调用对象,任何实现了__call__方法的对象均为可调用的.

通用模式

作为函数

函数返回包装原始函数调用的一个子函数

def mydecorator(func):
	def wrapped(*args, **kwargs):
		# do something
		ans=func(*args, **kwargs)
		# do something
		return ans
	return wrapped

作为类

当装饰器需要复杂的参数化或者依赖特定的状态,使用自定义类比较好

class DecoratorClass:
	def __init__(self, func):
		self.func=func
	def __call__(self, *args, **kwargs):
		# do something
		ans=self.func(*args, **kwargs)
		# do something
		return ans

参数化装饰器

需要两层包装,指定重复调用次数,每次被调用时会重复执行一个装饰器函数.

def rep(n=3):
    '''
    多次重复执行装饰函数,返回最后一次原始函数调用值作为结果
    '''
    def mydecorator(func):
        def wrapper(*args, **kwargs):
            ans=None
            for _ in range(n):
                ans=func(*args, **kwargs)
            return ans
        return wrapper
    return mydecorator

@rep(5)
def foo(): print("this is foo")
@rep()
def bar(): print("this is bar")
    
foo()
bar()

保存内省的装饰器

装饰器组合创建了新函数,并返回一个新对象,但是没有考虑到原始函数的meta-data,解决该问题的方法就是使用functools模块内置的wraps()装饰器.

from functools import wraps
def preserve_dec(func):
    @wraps(func)
    def wrapped(*args, **kwargs): return func(*args, **kwargs)
    return wrapped

@preserve_dec
def foo():
    """this is doc string"""

print(foo.__name__)
print(foo.__doc__)
    

本文地址:https://blog.csdn.net/qq_18822147/article/details/107661060

如您对本文有疑问或者有任何想说的,请 点击进行留言回复,万千网友为您解惑!

相关文章:

验证码:
移动技术网