python中函数分为函数、内置函数
Python所有的内置函数
自定义函数要使用def语句,依次写出函数名、括号、括号中的参数和冒号:,然后,在缩进块中编写函数体,函数的返回值用return语句返回。调用函数,使用函数名+()
1 def 关键字+函数名(): 2 函数体 3 return 可以终止函数,默认返回None 4 下面 hello()函数,没有返回值。如果保存了返回值,该值为 None: 5 >>> def hello(): 6 ... print 'hello world' 7 >>> 8 >>> res = hello() 9 hello world 10 >>> res 11 >>> print res 12 None 13 >>> type(res) 14 <type 'None'>
python里的函数可以返回一个值或者对象。只是在返回一个容器对象的时候有点不同,看起来像是能返回多个对象。
1 def foo(): 2 return ['xyz', 1000000, -98.6] 3 def bar(): 4 return 'abc', [42, 'python'], "Guido" 5 foo()函数返回一个列表, bar()函数返回一个元组。 由于元组语法上不需要一定带上圆括号, 所 6 以让人真的以为可以返回多个对象。
定义函数文档
1 文档的以贯例是多行字符串,第一行以大写字母开头以句点(.)结束(注:中文在V3.3中也可以),第二行是空行,从第三行开始是详细描述。强烈建议,为你重要的函数写文档字符串要遵循此贯例 2 def foo(): 3 ''' 4 foo() -- properly created doc string 5 ''' 6 函数体
函数的形参和实参
形参,只是一个形式,表示占据一个参数位置。
实参,是一个具体的参数,有它的实际意义。
Python中函数的实参有4种形式,分别是:
位置或关键字参数、仅位置的参数、任意数量的位置参数、任意数量的关键字参数
第一种:位置或关键字参数
这种参数是Python中默认的参数类型,定义这种参数后,可以通过位置参数,或者关键字参数的形式传递参数,这个是Python的默认参数类型
1 >>> def func(arg1, arg2="World!"): 2 print (arg1, arg2) 3 ## func可以通过位置参数形式调用 4 >>>func("Hello", "MitchellChu") 5 Hello MitchellChu 6 ## 也可以通过关键字参数的形式来调用func 7 >>>func(arg1="Hello", arg2="World!") 8 Hello World! 9 ## 当然,混合的方式也是完全没有问题的 10 >>>func("Hello", arg2="World!") 11 Hello World! 12 ## 不过如果你不能将关键字参数优先于位置参数传递给函数(方法) 13 ## 这个调用方法是不能接受的,因为优先级不一样.后面会说 14 >>> func(arg1="Hello", "World!") 15 SyntaxError: positional argument follows keyword argument
第二种方式:仅适用位置参数的形式
这种形式在需要将参数传递给函数(方法)时,仅能通过位置参数的传递方式。这种形式对于Python的开发者来说,暂时并没有办法使用。这种形式现在仅存在Python的很多内建的函数上:
1 >>> abs(-3) 2 abs(a=3) 3 ## Traceback (most recent call last): 4 ## File "<stdin>", line 1, in <module> 5 ## TypeError: abs() takes no keyword arguments 6 >>> pow(x=2,y=3) 7 ## Traceback (most recent call last): 8 ## File "<stdin>", line 1, in <module> 9 ## TypeError: pow() takes no keyword arguments 10 >>> pow(2,3) 11 ## 8
第三种:任意数量的位置参数(带单个星号参数)
任意数量的位置参数在定义的时候是需要一个星号前缀来表示,在传递参数的时候,可以在原有参数的后面添加任意多个参数,这些参数将会被放在元组内提供给函数(方法):
## 定义的时候,我们需要添加单个星号作为前缀
1 def func(arg1, arg2, *args): 2 print (arg1, arg2, args) 3 ##调用的时候,前面两个必须在前面,前两个参数是位置或关键字参数的形式,所以你可以使用这种参数的任一合法的传递方法 4 >>> func("hello", "Tuple, values is:", 2, 3, 3, 4) 5 hello Tuple, values is: (2, 3, 3, 4) 6 ##多余的参数将自动被放入元组中提供给函数使用.如果你需要传递元组给函数,你需要在传递的过程中添加*号 7 ## 请看下面例子中的输出差异: 8 >>> func("hello", "Tuple, values is:", (2, 3, 3, 4)) 9 hello Tuple, values is: ((2, 3, 3, 4),) 10 >>> func("hello", "Tuple, values is:", *(2, 3, 3, 4)) 11 hello Tuple, values is: (2, 3, 3, 4)
第四种:任意数量的关键字参数(带两个星号参数)
任意数量的关键字参数在定义的时候,参数名称前面需要有两个星号(**)作为前缀,这样定义出来的参数,在传递参数的时候,可以在原有的参数后面添加任意多个关键字参数,关键字参数是使用[参数名称=参数值]的形式进行传递:
1 >>> func("hello", "Dict, values is:", x=2, y=3, z=3) 2 hello Dict, values is: {'z': 3, 'x': 2, 'y': 3} 3 4 >>> func("hello", "Dict., values is:", **{'x':2, 'y':3, 'z':3,}) 5 hello Dict., values is: {'z': 3, 'x': 2, 'y': 3} 6 7 >>> func("hello", "Dict., values is:", s=3, **{'x':2, 'y':3, 'z':3,}) 8 hello Dict., values is: {'z': 3, 's': 3, 'x': 2, 'y': 3} 9 10 错误方法: 11 #提供多了参数 12 >>> func("hello", "Dict., values is:", {'x':2, 'y':3, 'z':3}) 13 Traceback (most recent call last): 14 File "<pyshell#57>", line 1, in <module> 15 func("hello", "Dict., values is:", {'x':2, 'y':3, 'z':3}) 16 TypeError: func() takes 2 positional arguments but 3 were given 17 18 ## 提供了重复的参数 19 >>> func("hello", "Dict., values is:", y=3, **{'x':2, 'y':3, 'z':3,}) 20 Traceback (most recent call last): 21 File "<pyshell#59>", line 1, in <module> 22 func("hello", "Dict., values is:", y=3, **{'x':2, 'y':3, 'z':3,}) 23 TypeError: func() got multiple values for keyword argument 'y'
总结:四种参数形式中仅有第二种Python没有提供定义的方法,其他三种在定义的时候也需要注意,定义的时候应该根据Python的解析规律进行定义,其中:
位置或关键字参数应该在最前面,其中,没有默认值的应该在有默认值的参数前面
任意数量位置参数应该放在所有位置或关键字参数的后面
任意数量关键字参数应该放在任意数量位置参数的后面
注意:任意数量位置参数和任意数量关键字参数只能在定义中定义一次。
## 各种参数的混合使用例子
1 def func(arg1, arg2='default', *args, **kwargs): 2 print ("arg1=%s, arg2=%s, args=%s, kwargs=%s" % (arg1, arg2, args, kwargs)) 3 func(1) 4 func(1,2) 5 func(1,2,3,4) 6 func(1,2,3,4,x=1,y=2) 7 func(1,2,x=1) 8 func(arg1=1) 9 func(1,x=1)
思考:函数接受变量作为参数时,接受的是变量的值还是变量的引用?
函数局部变量和全局变量:
在局部中调用全局变量(读取全局变量默认不用写。修改时需要),当全局变量为列表和字典,局部引用区域引用时不使用global时也是可以修改,不能重新赋值。全局变量与局部变量名称冲突时,在函数体内部优先使用局部变量
1 >>> li=[11,22,33] 2 >>> def name(li): 3 li=li.append(44) #全局变量在函数体内由于是引用,所以可以别修改,但是不能被赋值 4 >>> name(li) 5 >>> print(li) 6 [11, 22, 33, 44] 7 8 >>> li=[11,22,33] 9 >>> def name(li): 10 li='hello' #函数体内对全局变量赋值,结果没有改变 11 >>> name(li) 12 >>> print(li) 13 [11, 22, 33, 44] 14 15 16 >>> li=[11,22,33] 17 >>> def name(arg): 18 global li #使用global,可以对全局变量进行修改,不建议使用 19 li='hello world' 20 >>> name(li) 21 >>> print(li) 22 hello world
lambda表达式
lambda的主体是一个表达式,而不是一个代码块。仅仅能在lambda表达式中封装有限的逻辑进去。
lambda表达式是起到一个函数速写的作用。允许在代码内嵌入一个函数的定义。
1 >>> f2 = lambda a1: a1+100 2 # f2函数名称 关键字 函数参数 函数体 3 >>> f2(18) 4 118