Python Tips阅读摘要

发现了一本关于Python精通知识点的好书《Python Tips》,关于Python的进阶的技巧。摘录一些比较有价值的内容做为分享。html

*args and **kwargs

在函数定义的时候咱们常常看到*args和 **kwargs这两个定义对象。*args表明了函数定义中全部non-keyworded(这个词实在很难翻译)的传入参数,而**kwargs表明的全部带有keyworded的传入参数,举个栗子:python

def test_var_args(*args, **kwargs):
    print("args:{0}, kwargs:{1}".format(args,kwargs))
test_var_args(1,2,3)
>>>args:(1, 2, 3), kwargs:{}
test_var_args(a=1,b=2,c=3)
>>>args:(), kwargs:{'a': 1, 'c': 3, 'b': 2}

经过这个栗子咱们能够清晰地区分keyworded和non-keyworded的区别了。本质上来讲,args是一个数组,kwargs是一个字典。
args and *kwargs 最经常使用于装饰器,也能够用于monkey patching(猴子补丁),用来在运行时动态修改已有的代码,而不须要修改原始代码。json

  • monkey patching
    monkey patch指的是在运行时动态替换,通常是在startup的时候.
    用过gevent就会知道,会在最开头的地方gevent.monkey.patch_all();把标准库中的thread/socket等给替换掉.这样咱们在后面使用socket的时候能够跟日常同样使用,无需修改任何代码,可是它变成非阻塞的了.
    应用场景包括,一个已经定义好的函数被大量的引用,若是后面须要替换这个函数的话,直接在函数入口处进行替换便可。举个栗子,将ujson代替json:
main.py

import json  
import ujson  
def monkey_patch_json():  
    json.__name__ = 'ujson'  
    json.dumps = ujson.dumps  
    json.loads = ujson.loads  

monkey_patch_json()  
print 'main.py',json.__name__  
import sub  

======================
sub.py

import json  
print 'sub.py',json.__name__

能够看到json在该模块中被完美替换,这个方法也能够用来作单元测试使用。数组

Generators生成器

首先区分Iterable、Iterator和Iteration三个概念:任何具备__iter__()或__getitem__()方法的对象,Python就认为它是一个iterable;使用内置的iter()函数来生成iterator,iterator能够经过__next__()方法来获取下一个元素。iterator遍历元素的过程能够认为iteration。
生成器一样是可迭代对象,可是你只能读取一次,由于它并无把全部值存放内存中,它动态的生成值。
Yield是关键字, 用起来像return,yield在告诉程序,要求函数返回一个生成器,举个栗子:数据结构

def createGenerator():
    my_list=range(3)
    for  i in my_list:
        yield i*i
gen= createGenerator() 
print(next(gen))
print(next(gen))
print(next(gen))
print(next(gen)) #StopIteration

Map, Filter and Reduce

  • map
    Map的定义是将某函数处理全部输入参数,其定义为:

    map(function_to_apply, list_of_inputs)app

例如:异步

items = [1, 2, 3, 4, 5]
squared = list(map(lambda x: x**2, items))
当时这二者还能够经过lambda表达式进行多个函数处理同一个输入的状况,这是一个很是美妙的转换,栗子以下:socket

def multiply(x):
    return (x*x)
def add(x):
    return (x+x)

funcs = [multiply, add]
for i in range(5):
    value = list(map(lambda x: x(i), funcs))
    print(value)

# Output:
# [0, 0]
# [1, 2]
# [4, 4]
# [9, 6]
# [16, 8]

神奇的事情发生了,两个函数对于同一个输入参数都进行处理,并返回在告终果中。函数

  • filter

    filter(function_to_apply, list_of_inputs)单元测试

在大部分的状况下map和filter均可以经过list/dict/tuple Comprehensions来实现。
List Comprehensions语法:[expr for iter_var in iterable] 或 [expr for iter_var in iterable if cond_expr]
L = [expr for iter_var in iterable]:for iter_var in iterable的做用是依次取 iterable赋值给iter_var,而expr for iter_var in iterable的做用就是依次取值给iter_var,expr作运算后,继续循环,expr运算获得的值赋给变量L

map

map(function_to_apply, list_of_inputs)

经过函数对于结果进行处理,并返回汇集结果。例如:

from functools import reduce
product = reduce((lambda x, y: x * y), [1, 2, 3, 4])

# Output: 24

Collections

Collections包括几个经常使用的数据结构:

  • defaultdict : 是dict的子类,实现了dict的全部方法,功能使用上与dict.setdefault()相似,可是defaultdict构建时给出默认值。
  • orderdict:dict自排序。
  • counter:计数器,能够对iterator计数,也能够对list计数。
  • deque:队列。
  • nametuple:继承自tuple,我认为本质上是快速建立仅包括属性的类对象,从这个角度上看很是实用。
  • enum:枚举类型,可是必须注意,枚举成员自己类型就是枚举类型,所以若是须要将枚举成员用以读写及比较操做将会报错。 这篇教程中还讲了一些协程coroutine、异步IO的概念,但都属于技巧性的内容,讲的不透彻就再也不一一分享。
相关文章
相关标签/搜索