在知乎上看到的问题——python有哪些优雅的代码实现。html
下面的代码大概也算不上优雅。python
一下代码在python3中实现微信
更多内容可见:http://book.pythontips.com/en/latest/args_and_kwargs.htmlapp
lambda,又称匿名函数。当咱们在传入函数时,有些时候,不须要显式地定义函数,直接传入匿名函数更方便。函数
好比命名一个普通的函数:spa
def f(x): return x * x
在这里,f为函数名,x是函数的参数,x*x则是函数的返回结果。code
咱们能够换成lambda的形式则是:htm
>>> lambda x : x*x <function <lambda> at 0x7fa2d1298048> >>> f = lambda x : x*x >>> f(3) 9
lambda函数有一个限制就是函数中只能有一个表达式(事例中的x*x),该表达式的结果便是返回值。固然这个表达式能够用下面的一些技巧写的更“优雅”一些。对象
其中lambda函数返回是一个对象,其实在python中,绝大部分的都是对象,函数也是对象。因此咱们能将lambda函数赋给其它对象(事例中的f)。可是不建议这么作。通常使用lambda表达式时要注意:blog
1.逻辑简单,切忌在一个lambda表达式中作出很复杂的逻辑,这么作可能感受逼格很高可是代码的可读性会变得很是差。
2.一次性使用,就像上面所说的不建议使用f = lambda x:....的形式
map()
函数接收两个参数,一个是函数,一个是Iterable
,map
将传入的函数依次做用到序列的每一个元素,并把结果做为新的Iterator
返回。
好比咱们有一个函数f(x)=x2,要把这个函数做用在一个list [1, 2, 3, 4, 5, 6, 7, 8, 9]
上,就能够用map()
实现以下:
>>> def f(x): ... return x * x ... >>> r = map(f, [1, 2, 3, 4, 5, 6, 7, 8, 9]) >>> list(r) [1, 4, 9, 16, 25, 36, 49, 64, 81]
其中注意,传进map()的第一个参数是 f 而不是f(),其中f表示的是f函数对象自己而f()则是对函数f的调用。
map()
做为高阶函数,事实上它把运算规则抽象了,所以,咱们不但能够计算简单的f(x)=x2,还能够计算任意复杂的函数,好比,把这个list全部数字转为字符串:
>>> list(map(str, [1, 2, 3, 4, 5, 6, 7, 8, 9])) ['1', '2', '3', '4', '5', '6', '7', '8', '9']
固然,map()中还能够传入lambda表达式:
>>> list(map(lambda x: x*x,range(10))) [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
或者再结合一下:
>>> list(map(lambda x: str(x*x),range(10))) ['0', '1', '4', '9', '16', '25', '36', '49', '64', '81']
再看reduce
的用法。reduce
把一个函数做用在一个序列[x1, x2, x3, ...]
上,这个函数必须接收两个参数,reduce
把结果继续和序列的下一个元素作累积计算,其效果就是:
reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)
比方说对一个序列求和,就能够用reduce
实现:
>>> from functools import reduce >>> reduce(lambda x,y:x+y,[1,2,3,4]) 10
Python内建的filter()
函数用于过滤序列。
和map()
相似,filter()
也接收一个函数和一个序列。和map()
不一样的是,filter()
把传入的函数依次做用于每一个元素,而后根据返回值是True
仍是False
决定保留仍是丢弃该元素。
例如返回一个list中的奇数:
>>> list(filter(lambda x:x % 2 == 1,range(10))) [1, 3, 5, 7, 9]
列表推导,又称列表生成式,即List Comprehensions,是Python内置的很是简单却强大的能够用来建立list的生成式。
举个例子,要生成list [0,1, 2, 3, 4, 5, 6, 7, 8, 9]
能够用list(range(10))
:
>>> list(range(10)) [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
在python2中有点区别,python2中的range()直接生产列表而python3中生产的是一个range对象,须要经过list或者[]来生成。
>>> [x for x in range(10)] [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
或者进阶一点点:
>>> [x*x for x in range(10)] [0, 1, 4, 9, 16, 25, 36, 49, 64, 81] >>> [str(x) for x in range(10)] ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
>>> L = ['Hello', 'World', 'IBM', 'Apple'] >>> [s.lower() for s in L] ['hello', 'world', 'ibm', 'apple']
感受它的写法有点想lambda表达式。
而后其中也能够多几层的嵌套:
>>> [m + n for m in 'ABC' for n in 'XYZ'] ['AX', 'AY', 'AZ', 'BX', 'BY', 'BZ', 'CX', 'CY', 'CZ']
三层和三层以上的循环就不多用到了。
简单地讲,yield 的做用就是把一个函数变成一个 generator。
例如使用yield生成裴波那契数列:
def fab(max): n, a, b = 0, 0, 1 while n < max: yield b # print b a, b = b, a + b n = n + 1
>>> for n in fab(5): ... print n ... 1 1 2 3 5
使用yield的好处在于,它返回的是一个generator生成器。相似于python3中的range()和python2中的xrange()。带有 yield 的函数再也不是一个普通函数,Python 解释器会将其视为一个 generator,调用 fab(5) 不会执行 fab 函数,而是返回一个 iterable 对象!在 for 循环执行时,每次循环都会执行 fab 函数内部的代码,执行到 yield b 时,fab 函数就返回一个迭代值,下次迭代时,代码从 yield b 的下一条语句继续执行,而函数的本地变量看起来和上次中断执行前是彻底同样的,因而函数继续执行,直到再次遇到 yield。
由于返回的是一个生成器,因此可使用next()方法进行访问:
>>> f = fab(5) >>> next(f) 1 >>> next(f) 1 >>> next(f) 2 >>> next(f) 3 >>> next(f) 5
generator生成器,前面咱们看了列表推导,使用[]进行生成,其中把[]换成(),就建立了一个generator:
>>> L = [x * x for x in range(10)] >>> L [0, 1, 4, 9, 16, 25, 36, 49, 64, 81] >>> g = (x * x for x in range(10)) >>> g <generator object <genexpr> at 0x7fd2264607d8>
L
是一个list,而g
是一个generator。其中generator是可迭代的。
装饰器(Decorator),当咱们但愿为函数增长功能,可是却不想修改原函数又或者没有权限修改原函数的时候,就须要用到装饰器了。
好比咱们有一个函数:
def func(): print("I have a dream!") func() I have a dream!
是的,我有一个梦想!如今咱们想要知道我何时有一个梦想,就是咱们须要在执行函数的时候打印时间。那么:
'''定义一个装饰器''' def log_time(func): def wrapper(*args, **kw): print("run %s() and time is :" % func.__name__+str(datetime.datetime.now())) return func(*args,**kw) return wrapper @log_time def func(): print("I have a dream!") func()
输出:
run func() and time is :2016-10-10 14:26:08.296495 I have a dream!
本质上,decorator就是一个返回函数的高阶函数。其中,咱们给log_tim()传入一个参数,这个参数是一个函数对象,而且返回一个函数对象。而后在其中定义了wrapper(),这两个参数并无意义,只是为了说明这里面能够传入任意类型的参数。
而后用@语法将其放在函数定义处。其至关于:
func = log_time(func)
因为log_time()
是一个decorator,返回一个函数,因此,原来的func()
函数仍然存在,只是如今同名的func
变量指向了新的函数,因而调用func()
将执行新函数,即在log_time()
函数中返回的wrapper()
函数。
在使用装饰器时请注意:
用decorator修饰一个函数获得另外一个函数时,原来的那个函数依然是逻辑中心,而decorator所增长的只是相对外围的功能,不能那个什么宾那个什么主。
即便去掉装饰器,整个函数的逻辑仍需完整、清晰。
欢迎多来访问博客:http://liqiongyu.com/blog
微信公众号: