Python中的map函数和reduce函数的用法(精选5篇)
Python中的map函数和reduce函数的用法 第1篇
作者:廖雪峰 字体:[增加 减小] 类型:
这篇文章主要介绍了Python中的map()函数和reduce()函数的用法,代码基于Python2.x版本,需要的朋友可以参考下
Python内建了map()和reduce()函数,
如果你读过Google的那篇大名鼎鼎的论文“MapReduce: Simplified Data Processing on Large Clusters”,你就能大概明白map/reduce的概念。
我们先看map。map()函数接收两个参数,一个是函数,一个是序列,map将传入的函数依次作用到序列的每个元素,并把结果作为新的list返回。
举例说明,比如我们有一个函数f(x)=x2,要把这个函数作用在一个list [1, 2, 3, 4, 5, 6, 7, 8, 9]上,就可以用map()实现如下:
现在,我们用Python代码实现:
>>>def f(x):... return x * x...>>>map(f, [1, 2, 3, 4, 5, 6, 7, 8, 9])[1, 4, 9, 16, 25, 36, 49, 64, 81]
map()传入的第一个参数是f,即函数对象本身。
你可能会想,不需要map()函数,写一个循环,也可以计算出结果:
L = []for n in [1, 2, 3, 4, 5, 6, 7, 8, 9]: L.append(f(n))print L
的确可以,但是,从上面的循环代码,能一眼看明白“把f(x)作用在list的每一个元素并把结果生成一个新的list”吗?
所以,map()作为高阶函数,事实上它把运算规则抽象了,因此,我们不但可以计算简单的f(x)=x2,还可以计算任意复杂的函数,比如,把这个list所有数字转为字符串:
>>>map(str, [1, 2, 3, 4, 5, 6, 7, 8, 9])[1, 2, 3, 4, 5, 6, 7, 8, 9]
只需要一行代码。
再看reduce的用法。reduce把一个函数作用在一个序列[x1, x2, x3...]上,这个函数必须接收两个参数,reduce把结果继续和序列的下一个元素做累积计算,其效果就是:
reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)
比方说对一个序列求和,就可以用reduce实现:
>>>def add(x, y):... return x + y...>>>reduce(add, [1, 3, 5, 7, 9])25
当然求和运算可以直接用Python内建函数sum(),没必要动用reduce,
但是如果要把序列[1, 3, 5, 7, 9]变换成整数13579,reduce就可以派上用场:
>>>def fn(x, y):... return x * 10 + y...>>>reduce(fn, [1, 3, 5, 7, 9])13579
这个例子本身没多大用处,但是,如果考虑到字符串str也是一个序列,对上面的例子稍加改动,配合map(),我们就可以写出把str转换为int的函数:
>>>def fn(x, y):... return x * 10 + y...>>>def char2num(s):... return {0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8, 9: 9}[s]...>>>reduce(fn, map(char2num, 13579))13579
整理成一个str2int的函数就是:
def str2int(s): def fn(x, y): return x * 10 + y def char2num(s): return {0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8, 9: 9}[s] return reduce(fn, map(char2num, s))
还可以用lambda函数进一步简化成:
def char2num(s): return {0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8, 9: 9}[s]
def str2int(s): return reduce(lambda x,y: x*10+y, map(char2num, s))
也就是说,假设Python没有提供int()函数,你完全可以自己写一个把字符串转化为整数的函数,而且只需要几行代码!
练习
利用map()函数,把用户输入的不规范的英文名字,变为首字母大写,其他小写的规范名字。输入:[adam, LISA, barT],输出:[Adam, Lisa, Bart]。
Python提供的sum()函数可以接受一个list并求和,请编写一个prod()函数,可以接受一个list并利用reduce()求积。
Python中的map函数和reduce函数的用法 第2篇
这篇文章主要介绍了Python中map,reduce,filter和sorted函数的使用方法,是Python入门学习中的基础知识,需要的朋友可以参考下
map
map(funcname, list)
python的map 函数使得函数能直接以list的每个元素作为参数传递到funcname中, 并返回响应的新的list
如下:
def sq(x): return x*x #求x的平方map(sq, [1,3, 5,7,9]) #[1, 9, 25, 49, 81]
在需要对list中的每个元素做转换的时候, 会很方便
比如,把list中的每个int 转换成str
map(str, [23,43,4545,324]) #[23, 43, 4545, 324]
当然, 第二个参数是list, 也可以是tuple 或者是set类list结构的, dict 是不行的,不过返回的结果都是list
map(sq, (1,3, 5,7,9)) # tuple [1, 9, 25, 49, 81]map(sq, set([1,3, 5,3,7,9])) # set [1, 9, 81, 25, 49]
这里顺便说一下, dict的结构是用{} 表示的,如
{“name”: “Yi_Zhi_Yu”, “age”:25}
是直观的key-value形式, 那么如果{}中的是一个类list的结构呢, 如:
{“Yi_Zhi_Yu”, 25}
其实, 这就是set的最终返回形式, 等价于:
set([“Yi_Zhi_Yu”, 25])# 你会看到最终的输出形式是{25, Yi_Zhi_Yu}
那么, 自然{}有重复值得时候也会去重
{1,3, 5, 3, 7, 9} #{1, 3, 5, 7, 9}
reduce
reduce(funcname, list)
与map相比 , reduce类似于一个聚合类的应用方法, 把list中的参数, 依次传递给funcname, 每次funcname的参数都是上个funcname 执行结果和下一个list中的元素, 所以, funcname 的 参数必须是两个. 从执行过程看, 有点像递归
例如: 求range(1, 101)(不包括101)的和,
def c_sum(x, y): return x + y;reduce(c_sum, range(1,101)) #5050
filter
filter(funcname, list)
执行过程依次将list中的元素传递到funcname函数中, 根据funcname返回的True或False 保留或丢弃元素
例: 返回某个list中的所有int数据
def is_int(x): if isinstance(x, (int)): return True else: return False filter(is_int, [“Yi”,2, “3”, 4]) #[2, 4]sortedsorted( list, [comp_func])
排序方法, 第二个是可选参数, 根据可选参数返回的值, 对结果进行排序, comp_func 接受两个参数(x, y), 最终返回的结果应该是-1.0,1, 如果返回的是-1, 表示x
默认是正序排序:
sorted([3,4, 12, 5, 9, 1]) #[1, 3, 4, 5, 9, 12]
如果是需要倒序排列, 自定义方法:
Python中的map函数和reduce函数的用法 第3篇
代码如下:
class Foo(object):
static_attr = True
def method(self):
pass
foo = Foo()
这段代码实际上创造了两个对象,Foo和foo。而Foo同时又是一个类,foo是这个类的实例。
在C++里类型定义是在编译时完成的,被储存在静态内存里,不能轻易修改。在Python里类型本身是对象,和实例对象一样储存在堆中,对于解释器来说类对象和实例对象没有根本上的区别。
在Python中每一个对象都有自己的命名空间。空间内的变量被存储在对象的__dict__里。这样,Foo类有一个__dict__, foo实例也有一个__dict__,但这是两个不同的命名空间。
所谓“定义一个类”,实际上就是先生成一个类对象,然后执行一段代码,但把执行这段代码时的本地命名空间设置成类的__dict__. 所以你可以写这样的代码:
代码如下:
>>>class Foo(object):
...bar = 1 + 1
...qux = bar + 1
...print “bar: ”, bar
...print “qux: ”, qux
...print locals()
...
bar:2
qux:3
{qux: 3, __module__: __main__, bar: 2}
>>>print Foo.bar, Foo.__dict__[bar]
2 2
>>>print Foo.qux, Foo.__dict__[qux]
3 3
所谓“定义一个函数”,实际上也就是生成一个函数对象。而“定义一个方法”就是生成一
个函数对象,并把这个对象放在一个类的__dict__中。下面两种定义方法的形式是等价的:
代码如下:
>>>class Foo(object):
...def bar(self):
...return 2
...
>>>def qux(self):
...return 3
...
>>>Foo.qux = qux
>>>print Foo.bar, Foo.__dict__[bar]
>>>print Foo.qux, Foo.__dict__[qux]
>>>foo = Foo()
>>>foo.bar()
2
>>>foo.qux()
3
而类继承就是简单地定义两个类对象,各自有不同的__dict__:
代码如下:
>>>class Cheese(object):
...smell = good
...taste = good
...
>>>class Stilton(Cheese):
...smell = bad
...
>>>print Cheese.smell
good
>>>print Cheese.taste
good
>>>print Stilton.smell
bad
>>>print Stilton.taste
good
>>>print taste in Cheese.__dict__
True
>>>print taste in Stilton.__dict__
False
复杂的地方在`.`这个运算符上。对于类来说,Stilton.taste的意思是“在Stilton.__dict__中找taste. 如果没找到,到父类Cheese的__dict__里去找,然后到父类的父类,等等。如果一直到object仍没找到,那么扔一个AttributeError.”
实例同样有自己的__dict__:
代码如下:
>>>class Cheese(object):
...smell = good
...taste = good
...def __init__(self, weight):
...self.weight = weight
...def get_weight(self):
...return self.weight
...
>>>class Stilton(Cheese):
...smell = bad
...
>>>stilton = Stilton(100g)
>>>print weight in Cheese.__dict__
False
>>>print weight in Stilton.__dict__
False
>>>print weight in stilton.__dict__
True
不管__init__()是在哪儿定义的, stilton.__dict__与类的__dict__都无关。
Cheese.weight和Stilton.weight都会出错,因为这两个都碰不到实例的命名空间。而
stilton.weight的查找顺序是stilton.__dict__ =>Stilton.__dict__ =>
Cheese.__dict__ =>object.__dict__. 这与Stilton.taste的查找顺序非常相似,仅仅是
在最前面多出了一步。
方法稍微复杂些。
代码如下:
>>>print Cheese.__dict__[get_weight]
>>>print Cheese.get_weight
>>>print stilton.get_weight
<__main__.Stilton object at 0x7ff820669190>>
我们可以看到点运算符把function变成了unbound method. 直接调用类命名空间的函数和点
运算返回的未绑定方法会得到不同的错误:
代码如下:
>>>Cheese.__dict__[get_weight]()
Traceback (most recent call last):
File “”, line 1, in
TypeError: get_weight() takes exactly 1 argument (0 given)
>>>Cheese.get_weight()
Traceback (most recent call last):
File “”, line 1, in
TypeError: unbound method get_weight() must be called with Cheese instance as
first argument (got nothing instead)
但这两个错误说的是一回事,实例方法需要一个实例,
所谓“绑定方法”就是简单地在调用方法时把一个实例对象作为第一个参数。下面这些调用方法是等价的:
代码如下:
>>>Cheese.__dict__[get_weight](stilton)
100g
>>>Cheese.get_weight(stilton)
100g
>>>Stilton.get_weight(stilton)
100g
>>>stilton.get_weight()
100g
最后一种也就是平常用的调用方式,stilton.get_weight(),是点运算符的另一种功能,将stilton.get_weight()翻译成stilton.get_weight(stilton).
这样,方法调用实际上有两个步骤。首先用属性查找的规则找到get_weight, 然后将这个属性作为函数调用,并把实例对象作为第一参数。这两个步骤间没有联系。比如说你可以这样试:
代码如下:
>>>stilton.weight()
Traceback (most recent call last):
File “”, line 1, in
TypeError: str object is not callable
先查找weight这个属性,然后将weight做为函数调用。但weight是字符串,所以出错。要注意在这里属性查找是从实例开始的:
代码如下:
>>>stilton.get_weight = lambda : 200g
>>>stilton.get_weight()
200g
但是
代码如下:
>>>Stilton.get_weight(stilton)
100g
Stilton.get_weight的查找跳过了实例对象stilton,所以查找到的是没有被覆盖的,在Cheese中定义的方法。
getattr(stilton, weight)和stilton.weight是等价的。类对象和实例对象没有本质区别,getattr(Cheese, smell)和Cheese.smell同样是等价的。getattr()与点运算符相比,好处是属性名用字符串指定,可以在运行时改变。
__getattribute__()是最底层的代码。如果你不重新定义这个方法,object.__getattribute__()和type.__getattribute__()就是getattr()的具体实现,前者用于实例,后者用以类。换句话说,stilton.weight就是object.__getattribute__(stilton, weight). 覆盖这个方法是很容易出错的。比如说点运算符会导致无限递归:
代码如下:
def __getattribute__(self, name):
return self.__dict__[name]
__getattribute__()中还有其它的细节,比如说descriptor protocol的实现,如果重写很容易搞错。
__getattr__()是在__dict__查找没找到的情况下调用的方法。一般来说动态生成属性要用这个,因为__getattr__()不会干涉到其它地方定义的放到__dict__里的属性。
代码如下:
>>>class Cheese(object):
...smell = good
...taste = good
...
>>>class Stilton(Cheese):
...smell = bad
...def __getattr__(self, name):
...return Dynamically created attribute “%s” % name
...
>>>stilton = Stilton()
>>>print stilton.taste
good
>>>print stilton.weight
Dynamically created attribute “weight”
>>>print weight in stilton.__dict__
False
由于方法只不过是可以作为函数调用的属性,__getattr__()也可以用来动态生成方法,但同样要注意无限递归:
代码如下:
>>>class Cheese(object):
...smell = good
...taste = good
...def __init__(self, weight):
...self.weight = weight
...
>>>class Stilton(Cheese):
...smell = bad
...def __getattr__(self, name):
...if name.startswith(get_):
...def func():
...return getattr(self, name[4:])
...return func
...else:
...if hasattr(self, name):
...return getattr(self, name)
...else:
...raise AttributeError(name)
...
>>>stilton = Stilton(100g)
>>>print stilton.weight
100g
>>>print stilton.get_weight
>>>print stilton.get_weight()
100g
>>>print stilton.age
Traceback (most recent call last):
File “”, line 1, in
File “”, line 12, in __getattr__
AttributeError: age
Python中的map函数和reduce函数的用法 第4篇
这篇文章主要介绍了Python回调函数用法,以实例形式较为详细的分析了Python回调函数的定义、功能及相关使用技巧,需要的朋友可以参考下
本文实例讲述了Python回调函数用法,分享给大家供大家参考。具体分析如下:
一、百度百科上对回调函数的解释:
回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用为调用它所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。
二、什么是回调:
软件模块之间总是存在着一定的接口,从调用方式上,可以把他们分为三类:同步调用、回调和异步调用。同步调用是一种阻塞式调用,调用方要等待对方执行完毕才返回,它是一种单向调用;回调是一种双向调用模式,也就是说,被调用方在接口被调用时也会调用对方的接口;异步调用是一种类似消息或事件的机制,不过它的调用方向刚好相反,接口的服务在收到某种讯息或发生某种事件时,会主动通知客户方(即调用客户方的接口)。回调和异步调用的关系非常紧密,通常我们使用回调来实现异步消息的注册,通过异步调用来实现消息的通知。同步调用是三者当中最简单的,而回调又常常是异步调用的基础,因此,下面我们着重讨论回调机制在不同软件架构中的实现。
三、一个小例子:
#call.py import called def callback: print “in callback” def main(): #called.test() called.test_call(callback) print “in call.py” main() #called.py def test(): print “in called.py test()” def test_call(p_call): print “in called.py test_call()” p_call() joe@joe:~/test/python$ python call.py in called.py test_call() in callback in call.py joe@joe:~/test/python$
网上搜到的一个面向对象实现的例子:
当你要加入回调(Callback)功能的时候,代码往往会偏重于回调的实现而不是问题本身了。一个解决方法就是实现一个通用的基础类来解决回调的需求,然后再来实现你为某个事件(Event)所绑定(Binding)的方法(Method)。
代码如下:
class CallbackBase: def __init__(self): self.__callbackMap = {} for k in (getattr(self, x) for x in dir(self)): if hasattr(k, “bind_to_event”): self.__callbackMap.setdefault(k.bind_to_event, []).append(k) elif hasattr(k, “bind_to_event_list”): for j in k.bind_to_event_list: self.__callbackMap.setdefault(j, []).append(k) ## staticmethod is only used to create a namespace @staticmethod def callback(event): def f(g, ev = event): g.bind_to_event = ev return g return f @staticmethod def callbacklist(eventlist): def f(g, evl = eventlist): g.bind_to_event_list = evl return g return f def dispatch(self, event): l = self.__callbackMap[event] f = lambda *args, **kargs: map(lambda x: x(*args, **kargs), l) return f ## Sample class MyClass(CallbackBase): EVENT1 = 1 EVENT2 = 2 @CallbackBase.callback(EVENT1) def handler1(self, param = None): print “handler1 with param: %s” % str(param) return None @CallbackBase.callbacklist([EVENT1, EVENT2]) def handler2(self, param = None): print “handler2 with param: %s” % str(param) return None def run(self, event, param = None): self.dispatch(event)(param) if __name__ == “__main__”: a = MyClass() a.run(MyClass.EVENT1, mandarina) a.run(MyClass.EVENT2, naranja)
这里有一个类,它有两个事件(EVENT1和EVENT2)和两个处理函数(handler),
第一个处理函数handler1注册了EVENT1,而第二个处理函数handler2当EVENT1或者EVENT2发生的时候都会执行(即注册了全部的事件)。
运行函数(run)在MyClass的主循环中,它会将对应的事件派送(dispatch)出去。这(这里指dispatch函数)会返回一个函数,我们可以把所有需要传给这个函数的参数列表传给它。这个函数运行结束会返回一个列表(list),列表中是所有的返回值。
也许,使用Metaclass能够实现的更优雅一些吧。
Python中的map函数和reduce函数的用法 第5篇
这篇文章主要介绍了python中__call__内置函数用法,实例分析了python中__call__内置函数的原理与使用技巧,需要的朋友可以参考下
本文实例讲述了python中__call__内置函数的用法,分享给大家供大家参考。具体分析如下:
对象通过提供__call__(slef, [,*args [,**kwargs]])方法可以模拟函数的行为,如果一个对象x提供了该方法,就可以像函数一样使用它,也就是说x(arg1, arg2...) 等同于调用x.__call__(self, arg1, arg2),
模拟函数的对象可以用于创建仿函数(functor) 或代理(proxy)
class DistanceForm(object): def __init__(self, origin): self.origin = origin print “origin :”+str(origin) def __call__(self, x): print “x :”+str(x)p = DistanceForm(100)p
输出:
>>> origin :100x :2000