Python基础三. 函数、lambda、filter、map、reduce

一、概述

函数, 就是用一些语句组织起来实现一组特定的功能, 用来重复调用.

函数的作用及意义:最大化的重用代码和最小化的代码冗余以及对流程的分解.

Python中有哪些函数:

  • 内建的函数
  • 第三方模块中的函数
  • 自定义的函数

关于内置函数, 参考:

http://python.usyiyi.cn/python_278/library/functions.html

http://www.cnblogs.com/huangweimin/p/5619633.html

二、自定义函数

  • def语句声明, 函数也是一个对象, 函数名指向这个函数对象.
  • 函数可以传参, 位置参数、默认参数、收集参数 (形式参数、实际参数)
  • 函数用return将调用的的结果对象返回,  并且代表函数的结束
  • 自定义的函数不要和内置的对象冲突
  • 函数没有被调用不会执行
  • 理解作用域和命名空间, LEGB原则

//牢记: 函数也是一个对象,函数名只不过是指向函数对象的变量名

1、普通函数

def sayHi():                # 声明函数
	print 'Hello python'    # 函数体
print sayHi
sayHi()                      # 执行函数
结果:
<function sayHi at 0x00000000025209E8>    #函 数就是一对象,返回在内存中的地址
Hello python

//解释器遇到def函数语句,在内置中创建函数对象,函数名指向这个函数对象

Python基础三.  函数、lambda、filter、map、reduce

2、函数传参 (形式参数、实际参数)

函数可以传参数,关键字参数、默认参数、收集参数

1、关键字参数

def func(name,age):              # 定义形式参数
	print 'I am',name,'age',age
func('zhang', 25)                 # 传参,实际参数,对应关系

结果:
I am zhang age 25  
  • 形式参数可以说就是摆设,需要传实际的参数进去,它们是对应的关系
  • 先在内存中创建'zhang',25,然后将形式参数name,age分别指向它们
  • 如果不传参数会抛出异常TypeError
  • 函数的参数不是变量, 而是一种传值引用

2、默认参数

def func(name,age=19):              # age是默认参数
	print 'I am',name,'age',age
func('zhang')
func('li',age=21)  # 直接修改默认参数
func(name='wang',21)    # 同理
结果:
I am zhang age 19
I am li age 21
I am wang age 21
  • 默认参数相当于一个初始的参数,不能是不可变的对象
  • 如果不传默认参数,则使用默认参数,如果传相当于覆盖修改
  • 默认参数一定要放到最后面,可以有多个

3、收集参数 *args、**kwargs

number = (1,2,3,4,5)
def func(*args):                   # 定义收集参数
	print args
func()                             # 不传参数调用
func(1,2)                          # 传参
func('abcdefg')                    # 传字符串参数
func('zhang','li','zhao')          #
func(number)                       # 传一个序列
func(*number)                      # 传*序列
结果:
()                                 # 返回一个空(),说明*args的方式是构造一元组来装传过来的参数
(1, 2)
('abcdefg',)
('zhang', 'li', 'zhao')
((1, 2, 3, 4, 5),)
(1, 2, 3, 4, 5)
  • 说明*args构造的一个空tuple来装传过来的参数,如果要传一个列表或者元组需要在前面添加*抵消掉原来的tuple
dic = {"key1":"value1","key2":"value2"}
def func(**kwargs):
	print kwargs
func()           # 返回空{},说明**kwargs构造的是一个空的{}来装参数
func(key1='value1',key2='value2')
func(**dic)
结果:
{}
{'key2': 'value2', 'key1': 'value1'}
{'key2': 'value2', 'key1': 'value1'}
  • 说明**kwargs是用空{}来装参数,它只接受key=value形式的传参,否则会抛出错误TypeError,返回一个字典的形式(key不需要加引号)
  • 如果要传一个字典,需要在前面添加**

4、收集参数(就是*args、**kwargs的混用)

t1= (1,2,3)
dic = {'key1':'value1','key2':'value2'}
def func(*args,**kwagrs):
	print args,kwagrs
func()
func(1,2,3)
func(key1='value1',key2='value2')
func(1,2,3,key1='value1',key2='value2')
func(*t1,**dic)
结果:
() {}
(1, 2, 3) {}
() {'key2': 'value2', 'key1': 'value1'}
(1, 2, 3) {'key2': 'value2', 'key1': 'value1'}
(1, 2, 3) {'key2': 'value2', 'key1': 'value1'}
  • 收集参数*args、**kwargs可以混用,比较灵活,注意它们也有对应的关系,不能反着传

3、函数的返回值

  • 函数的返回值用return, 默认是None
  • 函数遇到了return就不会执行后面的语句,代表函数的结束
  • 函数只能return一种对象, 其实就是个tuple

1、函数执行遇到了return就不会往下面执行

def adds(x,y):
	return x+y
	print 'done'      	#不会执行
reslut = adds(10, 20)
print reslut
结果:
30

2、return与print

def adds(x,y):
	b = x+y
	print b
reslut = adds(10, 20)
print reslut
结果:
30
None                  # 没有retrun,默认返回None

def adds(x,y):
	b = x+y
	return b
reslut = adds(10, 20)
print reslut

结果:
30

//函数的return应该使用return而不是print

3、函数只能return一种对象,这也是函数的限制

>>> def adds():
...     return 1,{}
...
>>> adds()
(1, {})

//在adds()函数中,用return貌似返回int和dict两个对象,但是实际得到的是一个元组对象,说明return构造的是一个tuple对象返回调用的结果

4、函数的作用域

函数有自己的命名空间,即作用域:

  • 函数的内部变量不能被外部引用,除非global声明
  • 函数外部的变量能够被函数引用
  • LEGB原则,本地变量---上层函数---全局---内置

1、函数内的变量不能被外部引用,除非global声明

def func():
  x = 10
  print x
func()
10           

print x
NameError: name 'x' is not defined   #异常

如果global声明则可以调用:

def func():
  global x
  x = 10
  print x
func()
10           #结果

print x      #可以引用
10

2、全局与局部如冲突,局部优先,只作用在函数里面

a = 11
def fun1():
    a = 10
    print a
fun1()
print a
结果:
10
11              #注意并没有修改全局的变量a

如果添加global声明,则修改全局:

a = 11
def fun1():
    global a
    a = 10
    print a
fun1()
print a
结果:
10
10

3、内层函数优先

def func1():
  a = 10
  def func2():
    a = 11   #先找内层的a
    print a
  func2()
func1()
结果:
11

4、内层函数找不到再找外层函数

a = 1
def func3():
  a = 10
  def func4():
	print a   #内层函数找不到再找外层函数
  func4()
func3()

5、内层、外层函数都没有,找全局的

a = 1
def func3():
  def func4():
	print a     #内层、外层都没有
  func4()
func3()

三、lambda、map、filter、reduce

1、lambda

匿名函数就是没有名字的函数,lambda是匿名函数,可以实现简单的函数功能但作用有限

特点:

  1. 只是一种表达式函数,简单实现函数的功能
  2. 不需要函数名,本身也没有函数名,好处是有时候函数命名也不好管理
  3. 自动返回结果returen
  4. 同样可以传参数,收集参数、关键字参数、默认参数

用法:

"lambda" [parameter_list]: expression
parameter_list: 参数列表
expression: 表达式

1、简单的def函数可以用lambda表示

def func1(a,b):
	return a + b
print func1(10,20)
结果:
30

def func2(a):
	return a * 10
print func2(10)
结果:
100

用lambda表达式可以写成:

restult1 = lambda x,y: x + y           #x,y是形式参数
restult2 = lambda x: x * 10            #x是形式参数
print restult1(10,20)
30
print restult2(10)
100
  • 和函数一样,x,y可以看成是一个形式参数,可以传参

2、传默认参数、动态参数(*args,**kwagrs),默认参数也要放到最后面

func1 = lambda  arg2,arg1=10:arg2+arg1   #arg1是默认参数,放到后面
print func1(20)
30
print func1(20,20)
40

动态参数*args

func1 = lambda  *args:args
print func1(1,2,3,4)       #传数字
print func1('abcdefg')     #传字符串
print func1((1,2,3,4))     #传tuple
print func1(*(1,2,3,4))   #传*tuple
结果:
(1, 2, 3, 4)
('abcdefg',)
((1, 2, 3, 4),)
(1, 2, 3, 4)

传动态参数**kwargs

func2 = lambda **kwargs:kwargs
print func2()
print func2(key1="value1",key2="value2")
print func2(**{"key1":"value1","key2":"value2"})
结果:
{}
{'key2': 'value2', 'key1': 'value1'}
{'key2': 'value2', 'key1': 'value1'}
  • lambda函数传参和普通函数是一样的,*args、**kwargs分别构造的是空元组、空字典来装参数

3、def 声明函数是将函数名指向函数对象,而lamdba不是

def func1():
	pass
print func1

func2 = lambda a:a+1
print func2

结果:
<function <lambda> at 0x00000000025C09E8>  #始终返回的是lambda对象
<function func1 at 0x00000000025C0A58>

2、map

接收两个参数,函数和可迭代的对象,将function应用于iterable对象的每一个元素,返回结果的列表

用法:  map(function, sequence[, sequence, ...]) -> list (返回list)

li = [11,22,33,44,55,66,77]

1、给li列表中所有的元素加10返回一新的list

def func(args):
    return args + 10
reslut = map(func,li)      #map接收两个参数,一个函数,一个是列表,将里面中的每个元素作为参数传到func函数中最终得出结果
print reslut[21, 32, 43, 54, 65, 76, 87]

也可以用lambda表示:

result = map(lambda a:a+10,li)
print result
[21, 32, 43, 54, 65, 76, 87]

2、map接收多个序列

li = [11,22,33,44,55,66,77]
li2 = [22,33,44,55,66,77,88]
result = map(lambda a,b:a+b,li,li2)
print result
[33, 55, 77, 99, 121, 143, 165]
  • map函数遍历序列做为参数传给一个函数经过处理,返回一个新的列表。序列可以有个,可以是list和tuple  
  • map是高阶函数,一个函数作为参数传给另一函数

3、filter

对于序列中的元素进行筛选,最终获取符合条件的序列

参考

用法: filter(function or None, sequence)

li = [11,23,18,44,55,21]

1、filter函数从li列表中每取一个元素应用到func,进行筛选,得出符合条件的元素

def func(*args):
    for i in args:
        if i > 22:
            return i
reslut = filter(func, li)  #从li中每取一个元素作为参数传给func,返回符合条件的元素.
print reslut
[23, 44, 55]

等同于:

li = [11,23,18,44,55,21]
reslut = filter(lambda arg: arg > 22,li)
print reslut
[23, 44, 55]
  • 如果li是字符串返回的也是字符串、如果是元组返回的也是元组

4、reduce

归纳的意思,接受两个参数: 函数、序列型对象,从序列性的对象中拿出两个元素作作为参数传给函数,累积操作。返回一个值

用法: reduce(function, sequence[, initial]) -> value

  • initial: 初始值
reduce(...)
    reduce(function, sequence[, initial]) -> value

    Apply a function of two arguments cumulatively to the items of a sequence,
    from left to right, so as to reduce the sequence to a single value.
    For example, reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]) calculates
    ((((1+2)+3)+4)+5).  If initial is present, it is placed before the items
    of the sequence in the calculation, and serves as a default when the
    sequence is empty.

reduce

计算1*2*3*4*5

def func(x,y):
	return x * y
reslut = reduce(func, [1,2,3,4,5])
print reslut
120

等同于:
reslut1 = reduce(lambda x,y:x*y,[1,2,3,4,5])
print reslut1
120

也可以指定初始值initial

reslut1 = reduce(lambda x,y:x*y,[2,2,3,4,5],10)
print reslut1
2400

PS: 所以reduce函数就是从序列中拿出两个元素作用到函数中进行累积操作

总结:

  1. 函数的种类,内置函数、第三方模块函数、自定义函数
  2. def函数定义,函数名是函数对象的指向, 不要和内置函数冲突
  3. 函数可以传参, 关键字、默认、收集参数,默认参数要放到最后面
  4. 参数是函数的入口,return是函数的出口
  5. 函数的return只能返回一种对象,就是tuple
  6. 注意函数的作用域,全局与局部变量的关系,尽量不用使用全局变量
  7. 函数调用应该用return而不是用print,return代表函数的结束,函数执行完后内部对象会被回收
  8. 一个函数尽量只做一件事情

 

上一篇:EJB_开发消息驱动bean


下一篇:C# WPF 滚动字幕实现