python函数
- 函数名其实就是指向一个函数对象的引用,完全可以把函数名赋给一个变量,相当于给这个函数起了一个“别名”.
- 函数是可调用对象,可以使用内置函数
callable(obj)
,判断对象是否可以调用 - python函数内没有写return语句时,默认执行完后返回一个空对象None。return None可以简写为return
a = type # 变量a指向type函数
a(1) # <class 'int'> ,所以也可以通过a调用type函数
callable(type) # True
函数返回多个值
- python的函数返回多个值,实际上就是返回一个tuple
def test():
return 1,2
test() # (1,2) 返回元组
常用内置函数
-
isinstance(obj, class_or_tuple, /)
# Return whether an object is an instance of a class or of a subclass thereof.
isinstance(1, int) # True
isinstance(1, (int, str)) # True,相当于isinstance(1, int) or isinstance(1, str)
-
callable(obj, /)
# Return whether the object is callable
函数的参数
- 在Python中定义函数,可以用位置参数或者说必选参数、默认参数、可变参数args、关键字参数*kwargs和命名关键字参数,这5种参数都可以组合使用。
- 参数定义的顺序必须是:必选参数、默认参数、可变参数、命名关键字参数和关键字参数。
def test(a, b):
print(a, b)
test(1, 2) # 输出:1 2,直接按顺序传递位置参数
test(b=2, a=1) # 输出:1 2,根据形参的名字来传递参数,可以不按顺序
test(a=1, 3) # 报错:位置参数必须第一
定义默认参数
- 定义默认参数要牢记一点:
默认参数必须指向不变对象!
- 下面是默认参数是可便对象时每一次传递默认参数返回的结果不一样的例子
def add_end(L=[]):
L.append('END')
return L
add_end() # 第一次默认参数调用返回:['END']
add_end() # 第二次默认参数调用返回:['END', 'END']
add_end() # 第三次默认参数调用返回:['END', 'END', 'END']
- 原因解释如下:
Python函数在定义的时候,默认参数L的值就被计算出来了,即[],因为默认参数L也是一个变量,它指向对象[],每次调用该函数,如果改变了L的内容,则下次调用时,默认参数的内容就变了,不再是函数定义时的[]了。
可变参数和关键字参数
-
可变参数*args
:可变参数允许传入0个或任意个参数,这些可变参数在函数调用时自动组装为一个tuple传给形参。
# 所有条件都是True才返回True(a&b&c&...),用于解决需要多个skip条件
def is_all_true(a, *args)->bool:
result = bool(a)
for n in args:
result = result & bool(n)
return result
is_all_true(True, 1)
-
关键字参数**kwargs
:关键字参数允许你传入0个或任意个含参数名的参数,这些关键字参数在函数内部自动组装为一个dict传给形参。
def test(a, **kwargs):
print(a, kwargs)
test(1) # 1 {}
test(1, name="a", age=28) # 1 {name="a", age=28}
-
命名关键字参数keyword-only
:python3引入,定义的时候是位置参数但是调用的时候必须使用关键字参数传参。命名的关键字参数是为了限制调用者可以传入的参数名
def test1(a, *, x, y): # x,y都变成keyword-only参数
print(a, x, y)
test1(1) # 报错 missing 2 required keyword-only argument
test1(1, x=1, y=2) # 返回:1 1 2
def test2(*args, x, **kwargs): # x 即keyword-only参数
print(args, x,kwargs)
test2(1,2, x=3) # 返回: (1,2) 3 {}
参数组合
- 先满足位置参数,再满足默认参数,再满足args或kw
def test(a, b=None, *args, **kw):
print(a,'--',b,'--',args,'--',kw)
test(1, "cc") # 1 -- cc -- () -- {}
test(1, "cc", "cc") # 1 -- cc -- ('cc',)
test(1, b="cc") # 1 -- cc -- () -- {},b="cc"会传递给默认参数b而不是kw
test(1, c="cc") # 1 -- None -- () -- {'c': 'cc'}
test(1, b="cc", c="cc") # 1--cc--()--{'c': 'cc'}
test(1, b="cc", "cc") # 报错:SyntaxError: positional argument follows keyword argument
test(1, "cc", "cc") # 1 -- cc -- ('cc',) -- {}
test(1, "cc", c="cc") # 1--cc--()--{'c': 'cc'}
python不需要函数重载
- 函数重载override:当两个函数除了 参数类型和参数个数不同 外,其函数名称和功能完全相同,此时才使用函数重载。
- python函数不需要解决函数重载的两个问题: 对于可变参数类型,python可以接受任意类型的参数;对于可变参数个数,python可以使用缺省参数。
函数注释
函数注释:python3新增特性,定义函数的时候可以为函数添加参数注释和返回值注释。
- 参数注释: type类型/str类型/dict类型,格式:
func(参数: 参数注解)
- 返回值注释: type类型/str类型/dict类型,格式:
func()->返回值注解:
-
函数名.__annotations__
,返回函数的注解,dict类型
def sum(a: int, b: dict(type=int, help='arg b', c: 'arg c'))->int:
return a+b
# 参数a的注解值类型为 type , b 为 dict, c 为 str
sum.__annotations__
# {'a': <class 'int'>, b: {'type': <class 'int'>, 'help': 'arg b'}, 'c': 'arg c', 'return': <class 'int'>}
注意:
type=int, 返回{'type': <class 'int'>}
,type='int', 返回的是{'type': 'int'}
由于函数注释是dict类型,是可变的,所以可以在程序运行时动态的增加注释
def sum(a: dict(type=int), b: int)->dict(type=dict, help='return value'):
sum.__annotations__['a']['help'] = 'arg a' # 调用函数时,动态增加参数a的注释
return a+b
sum(1, 2)
print(sum.__annotations__['a']) # {'type': <class 'int'>, 'help': 'arg a'}