Python-2 函数、参数
函数
- 
help(abs):查看函数abs的帮助信息。
- 
pass:占位符,还没想好怎么写,先pass,让程序跑起来看一下。- 比如在 if 语句下,定义函数如下。
 def my_abs(x): if not isinstance(x, (int, float)): raise TypeError('bad operand type') if x >= 0: return x else: return -x
- 
定义函数下,第一行使用: "函数的说明注释"。
- 
Python 可以返回多个值, return x, y。
- 
接收: x, y = testFunc(xxx)。
- 返回的其实是一个元组,多个变量接收一个元组,则元组将元素按顺序赋值给变量。
- isinstance(x, (int, float)):- x是否为 int 或 float 类型。
 - raise TypeError('错误提示文本'):抛出指定提示语的类型错误。
默认参数
不同于 java ,Python 可以有默认参数,可写成 def power(x, n=2),此时调用 power(5),相当于 power(5, 2)
默认参数为可变类型的误区
有一函数 def add_end(L[]):多次调用 add_end()(不传参数,使用默认参数),则会发现这个默认参数被存下来了。
def add_end(L=[]):
    L.append('END')
return L
>>> add_end()
['END']
>>> add_end()
['END', 'END']
>>> add_end()
['END', 'END', 'END']
- def中,默认参数被定义了,只计算一次,拥有了一个内存地址。直接调用默认参数的话(没给参数),会对该地址进行操作。如果是列表、字典或类实例等可变对象时,将会导致该默认参数发生改变。
所以应该尽量使默认参数为不可变参数。
def add_end(L=None):
    if L is None:
        L = []
    L.append('END')
return L
- 这里,def中的参数是固定不变的。在函数里每次都新建了一个列表,多次调用函数使用默认参数,都会独自生成。
位置参数
函数的不加任何东西的参数默认是位置参数(必需参数),不可缺少。
函数内可以再定义函数,并且这个内部函数可以访问外部函数的参数和局部变量。
- 
位置参数在定义里必须是在开头位置的。 
- 
(此点学习关键字参数后可懂)多种类型参数调用函数时,位置参数必须要也在开头对应位置。除非也将位置参数,使用其关键字传入。 比如函数 def test(a, b=100, c=100):test(b=2, 1)是错误的。而test(b=2, a=1)是可以的。一般的常用方式是 test(1, 2),即位置参数一般不用关键字。而关键字参数在有多个关键字可选、要区分的话,常使用关键字传入:test(1,b=2, c=3)。
可变参数
定义可变参数的函数(java 里的 ...):
def calc(*numbers)
- 可变参数 numbers在函数里被合并为一个元组numbers,在外面调用函数直接传进来多个值即可。
- 调用函数时,也可以使用:calc(*tuple1),直接将一个元组/列表作为参数(类似于解构)。
def computed(x, y, *z):
    print("可变参数:", z)
    print("两个位置参数:", x, y)
x = [1, 1, 2, 2]
computed(*x)
可变参数: (2, 2)
两个位置参数: 1 1
关键字参数
关键字参数 **kw 相当于可变参数 *args 的变种,也是一种可选的,但是它是键值对形式。
主要是可以让我们在使用函数的时候,不需要顾及参数的位置,直接将对应关键字传入即可。
注意到关键字参数与默认参数实际上是一样的。
def person(name, age, **kw):
- kw是 字典,键值对;- name,- age为位置参数。
- name,- age位置参数是必要的,而关键字参数是次要的,扩展的。
- 调用:person('Bob', 18, city='Xiamen', job='ceo'),必须传入参数名,否则会被识别为位置参数,出现错误。
- 同样,调用函数时使用 person('Bob', 18, **extra),将一个名为extra的字典做为参数传入。
- 值得注意的是,这里的 **extra只是extra的一个浅拷贝,函数内的对不可变元素的操作不会影响外部的extra,但操作可变元素有影响。
- 位置参数可以使用关键字参数传入。此时不需要考虑他们的顺序问题。
命名关键字参数/仅限关键字参数:限制关键字参数的名字
def person(name, age, *, city='Beijing', job):  # 在星号后面写上关键字参数应有的键名
这里除必须参数外,还限制必须【要有且仅有】名为 city,job 的参数传进来。
- 如果有可变参数,可变参数后面的关键字参数可以不再用 *分隔了,后面默认是命名关键字参数:def person(name, age, *args, city, job)。
- 如果关键字参数有默认值,则可以不用必须传入
- 比如这样可以调用上面小标题下的函数:person('Jack', 24, job='Engineer')
 
- 比如这样可以调用上面小标题下的函数:
强制位置参数/仅限位置参数
在上面的参数中的,调用时:
- 如 f(10)使用的是位置参数,没有,是没有带名字的参数
- f(a=10)使用的是关键字参数/命名关键字参数,带有名字
Python 3.8 新增了一种参数 /,使得前面的参数调用必须使用位置参数:
def f(a, b, /, c, d, *, e, f)
  print(a, b, c, d, e, f)
以下使用方法是正确的:
f(10, 20, 30, d=40, e=50, f=60)
以下使用方法会发生错误:
f(10, b=20, c=30, d=40, e=50, f=60)  # b不能使用关键字参数的形式
f(10, 20, 30, 40, 50, f=60)  # e必须使用关键字参数的形式
仅限位置参数应放在
/(正斜杠)前。/用于在逻辑上分割仅限位置形参与其它形参。仅限关键字参数放在
*之后。
参数组合
有多种参数的话,按照逻辑以及要求,必须按顺序来:必选参数(位置参数)、默认参数、可变参数、命名关键字参数和关键字参数。
def f(a, b, c=0, *, d, **kw):
#     必 必  默    命名  关键
# f函数要有a,b,可选c参数,还必须要有d=value
# 因为有**kw,所以还可有其他带名字的键值对传入
# 这里没有演示可变参数:def f(a, b, c=0, *args, d, **kw)
对于任意函数,都可以通过类似 func(*args, **kw) 的形式调用它,无论它的参数是如何定义的。
- *args包括必选参数、可变参数。
- **kw包括默认参数、关键字参数、命名关键字参数。
递归函数
解决递归调用栈溢出的方法:尾递归
大多数编程语言没有针对尾递归做优化,Python 解释器也没有做优化,所以,即使把阶乘的 fact(n) 自定义函数改成尾递归方式,也会导致栈溢出。
匿名函数
lambda 表达式,它是一个表达式,只包含一个语句,而不是一个代码块。仅能在 lambda 表达式中封装有限的逻辑进去。
lambda [arg1[, arg2,.....argn]]:expression
# 冒号前参数,冒号后表达式
示例:
sum = lambda arg1, arg2: arg1 + arg2
# 调用sum函数
print("相加后的值为: ", sum(10, 20))
print("相加后的值为: ", sum(20, 20))
 
    
 
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号