Python很棒,它有不少高级用法值得细细思索,学习使用。本文将根据平常使用,总结介绍Python的一组高级特性,包括:列表推导式、迭代器和生成器、装饰器。python
场景1:将一个三维列表中全部一维数据为a的元素合并,组成新的二维列表。缓存
最简单的方法:新建列表,遍历原三维列表,判断一维数据是否为a,若为a,则将该元素append至新列表中。
缺点:代码太繁琐,对于Python而言,执行速度会变慢不少。
针对场景1,咱们首先应该想到用列表解析式来解决处理,一行代码便可解决:app
lista = [item for item in array if item[0] == 'a']
那么,何为列表解析式?
官方解释:列表解析式是Python内置的很是简单却强大的能够用来建立list的生成式。
强大具体如何体现?
能够看到,使用列表解析式的写法更加简短,除此以外,由于是Python内置的用法,底层使用C语言实现,相较于编写Python代码而言,运行速度更快。函数
场景2: 对于一个列表,既要遍历索引又要遍历元素。性能
这里可使用Python内建函数enumerate,在循环中更好的获取得到索引。学习
array = ['I', 'love', 'Python'] for i, element in enumerate(array): array[i] = '%d: %s' % (i, seq[i])
可使用列表推导式对其进行重构:测试
def getitem(index, element): return '%d: %s' % (index, element) array = ['I', 'love', 'Python'] arrayIndex = [getitem(index, element) for index, element in enumerate(array)]
听说这种写法更加的Pythonic。大数据
总结:若是要对现有的可迭代对象作一些处理,而后生成新的列表,使用列表推导式将是最便捷的方法。设计
这里的迭代能够指for循环,在Python中,对于像list,dict和文件等而言,均可以使用for循环,可是它们并非迭代器,它们属于可迭代对象。
什么可迭代对象
最简单的解释:可使用for...in...语句进行循环的对象,就是可迭代对象(Iterable),可使用isinstance()方法进行判断。日志
from collections import Iterable type = isinstance('python', Iterable) print type
什么是迭代器
迭代器指的是可使用next()方法来回调的对象,能够对可迭代对象使用iter()方法,将其转换为迭代器。
temp = iter([1, 2, 3]) print type(temp) print next(temp)
此时temp就是一个迭代器。因此说,迭代器基于两个方法:
可理解为可被next()函数调用并不断返回下一个值的对象就是迭代器,在定义一个装饰器时将须要同时定义这两个方法。
迭代器的优点
在构建迭代器时,不是将全部的元素一次性的加载,而是等调用next方法时返回元素,因此不须要考虑内存的问题。
迭代器应用场景
那么,具体在什么场景下可使用迭代器呢?
生成器是一种高级迭代器,使得须要返回一系列元素的函数所需的代码更加的简单和高效(不像建立迭代器代码那般冗长)。
生成器函数
生成器函数基于yield指令,能够暂停一个函数并返回中间结果。当须要一个将返回一个序列或在循环中执行的函数时,就可使用生成器,由于当这些元素被传递到另外一个函数中进行后续处理时,一次返回一个元素能够有效的提高总体性能。
常见的应用场景是使用生成器的流数据缓冲区。
生成器表达式
生成式表达式是一种实现生成器的便捷方式,将列表推导式的中括号替换为圆括号。
和列表推导式的区别:列表生成式能够直接建立一个表,可是生成器表达式是一种边循环边计算,使得列表的元素能够在循环过程当中一个个的推算出来,不须要建立完整的列表,从而节省了大量的空间。
g = (x * x for x in range(10))
总结:生成器是一种高级迭代器。生成器的优势是延迟计算,一次返回一个结果,这样很是适用于大数据量的计算。可是,使用生成器必需要注意的一点是:生成器只能遍历一次。
lambda表达式纯粹是为了编写简单函数而设计,起到了一个函数速写的做用,使得简单函数能够更加简洁的表示。
lambda和def的区别
lambda表达式能够省去定义函数的过程,让代码更加的简洁,适用于简单函数,编写处理更大业务的函数须要使用def定义。
lambda表达式常搭配map(), reduce(), filter()函数使用
#将一个列表中的数字转换为字符串 map(str, [1,2,3,4,5,6])
reduce():函数接收两个参数,一个是函数,另外一个是序列,可是,函数必须接收两个参数reduce把结果继续和序列的下一个元素作累积计算,其效果就是reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)。
filter():该函数用于筛选,将传入的函数,依次做用于每一个元素,而后根据函数的返回值是True仍是False,决定是留下仍是丢弃该元素。
装饰器本质是一个Python函数,它可让其它函数在没有任何代码变更的状况下增长额外功能。有了装饰器,咱们能够抽离出大量和函数功能自己无关的雷同代码并继续重用。常常用于具备切面需求的场景:包括插入日志、性能测试、事务处理、缓存和权限校验等。
那么为何要引入装饰器呢?
场景:计算一个函数的执行时间。
一种方法就是定义一个函数,用来专门计算函数的运行时间,而后运行时间计算完成以后再处理真正的业务代码,代码以下:
import time def get_time(func): startTime = time.time() func() endTime = time.time() processTime = (endTime - startTime) * 1000 print "The function timing is %f ms" %processTime def myfunc(): print "start func" time.sleep(0.8) print "end func" get_time(myfunc) myfunc()
可是这段代码的逻辑破坏了原有的代码逻辑,就是对全部func函数的调用都须要使用get_time(func)来实现。
那么,有没有更好的展现方式呢?固然有,那就是装饰器。
编写简单装饰器
结合上述实例,编写装饰器:
def get_time(func): def wrapper(): startTime = time.time() func() endTime = time.time() processTime = (endTime - startTime) * 1000 print "The function timing is %f ms" %processTime return wrapper print "myfunc is:", myfunc.__name__ myfunc = get_time(myfunc) print "myfunc is: ", myfunc.__name__ myfunc()
这样,一个简单的完整的装饰器就实现了,能够看到,装饰器并无影响函数的执行逻辑和调用。
在Python中,可使用"@"语法糖来精简装饰器的代码,将上例更改成:
@ get_time def myfunc(): print "start func" time.sleep(0.8) print "end func" print "myfunc is: ", myfunc.__name__ myfunc()
** 装饰器的调用顺序**
装饰器能够叠加使用,若多个装饰器同时装饰一个函数,那么装饰器的调用顺序和@语法糖的声明顺序相反,也就是:
@decorator1 @decorator2 def func(): pass
等效于:
func = decorator1(decorator2(func()))
被装饰的函数带参数
上述实例中,myfunc()是没有参数的,那若是添加参数的话,装饰器该如何编写呢?
#被装饰的函数带参数 def get_time3(func): def wrapper(*args, **kwargs): startTime = time.time() func(*args, **kwargs) endTime = time.time() processTime = (endTime - startTime) * 1000 print "The function timing is %f ms" %processTime return wrapper @ get_time3 def myfunc2(a): print "start func" print a time.sleep(0.8) print "end func" a = "test" myfunc2(a)
带参数的装饰器
装饰器有很大的灵活性,它自己支持参数,例如在上述实例中,@get_time装饰器惟一的参数就是执行业务的函数,固然也能够在装饰器中添加参数,加以逻辑判断。
Python中,常见的类装饰器包括:@staticmathod、@classmethod和@property
以上,是本次整理的Python高级用法,本文将持续更新。