python基础(4)

参考:www.liaoxuefeng.com/wiki/101695…

函数的定义和调用

def 函数标识符(形参):
    函数体内容
    return [内容,没有定义return值,返回None]
def test():
    pass

def test1():
    return 1

# x就是函数test2的形参
def test2(x):
    return x**2
 
def test3()
    return 1,2

a = test()
print(a) # 打印None

b = test1()
print(b) # 打印1

# test(2) 2就是实参
c = test2(2)
print(c) # 打印4

# 会把多个返回值封装成元祖,如果=左侧有多个标识符,可以解构赋值
d,e = test3() 
print(d,e) # d=1,e=2

函数传参

传参方式

  • 位置传参:严格按照参数位置传参,形参和实参的数量必须对应
def test(x, y, z):
    print(x,y)

test(1,2) # 错误,因为参数有3个
test(1,2,3) 
  • 关键字传参:调用函数使用形参名字传入参数,可以与形参的顺序不同
def test(x, y, z):
    print(x, y, z)


test(z=3, y=2, x=1)
  • 注意:位置传参必须在关键字传参前
def test(x, y, z):
    print(x, y, z)


test(1, 2, 3)
test(z=3, y=2, x=1)
test(y=2, x=1, z=3)
test(1, y=2, z=3)
test(x=1, 2, 3) # 报错
  • 总结:传参方式方式总共有2种:1.位置传参 2.关键字传参。位置传参与形参一一对应,位置传参需带上形参名,可以不和形参一一对应,位置传参必须在关键字参数之前

参数类型

python函数参数非常复杂,需要理解才能良好的使用

形参默认值(默认参数)

python定义函数时,可以为形参设置默认的值,调用者可以不传入该参数,使用默认值简化函数调用

def add(x=1, y=2):
    print(x + y)

def add2(x=2,y): # 定义函数也要遵循位置参数在前,关键字参数在后
    print(x+y)

add() # 使用形参默认值x=1,y=2
add(3, 4)
add(y=3, x=4)
add(3, y=5)
add(x=6, 10) # 错误,记住位置参数必须在关键字参数之前

可变位置参数

允许调用方传入0到n个位置参数,在形参前加上*

def add(iterable):
    num = 0
    for i in iterable:
        num += i
    print(num)


def add2(*nums):
    num = 0
    for i in nums:
        num += i
    print(num)


add([x for x in range(101)])
add2(1, 3, 4, 5, 6)

当形参不加*,传入的参数必须是可迭代的对象,加上*,可以传入任意值,nums会把参数封装成元祖

可变关键字参数

允许调用方传入0到n个关键字参数,在形参前加上**

def test(**kwargs):
    for k, v in kwargs.items():
        print(k, v)


test(a=1, b=2, c=3)
  • 注意:可变位置参数必须在可变关键字参数前面

混合使用

def showConfig(a, b, *args, **kwargs):
    pass
def showConfig(a, b=2, *args, **kwargs):
    pass
def showConfig(a=2, b, *args,**kwargs): # 错误,位置参数必须在关键字参数之前
    pass
def showConfig(a, b, **kwargs, *args): # 错误,可变关键字参数必须在可变位置参数后面
    pass
def fn(x, y, *args, **kwargs):
    print(x, y, args, kwargs)


fn(1, 2, 3, 4, 5, a=1, b=2)
fn(1, 2)
fn(1, 2, 3)
fn(1, 2, a=1, b=2) # a和b都被kwargs接收
fn(x=1, y=2, z=3)  # z被kwargs接收
fn(x=1, y=2, 1, 2) # 位置参数必须在关键字参数前
fn(1, 2, x=3, y=4) # got multiple values for argument 错误

keyword-only参数

python3后增加keyword-only参数,在一个*号或可变位置参数后定义的形参,只能通过关键字参数传参

def fn(*args, a, b):
    print(args, a, b)

def fn1(**kwargs, a, b): # 直接语法错误
    pass

def fn2(*args, a=1, b=2): # 可以设置默认值
    print(args, a, b)

fn(1, 2, 3, a=4, b=4)
fn(a=4, b=4)
fn(1, 2, 3, 4, 5) # 报错:missing 2 required keyword-only arguments: 'a' and 'b'
fn2()

  • 如果不需要前面的可变位置参数,可简写成*
def fn3(*, a, b=1):
    print(a, b)
    
fn3(a=3)

positional-only参数

在python3.8后,增加只允许位置传参的参数,在/前的参数都是位置传参

image.png

结合所有的参数类型

image.png

  • a和b只能通过位置传参的方式传参,a=或b=都将会报错

  • c和d可以通过位置传参或关键字传参

  • e和f只能通过关键字传参

参数解构

使用*或**将可迭代对象结构,将所有的值作为函数的参数

def add(*nums):
    num = 0
    for i in nums:
        num += i
    print(num)

def fn(*args):
    for i in args:
        print(i)


l = [ x for x in range(101) ]
d = {"a": 1, "b":2, "c":3}

add(*d.values())
add(l) # 报错,因为是把整个列表当参数传入
add(*l) # 把l列表的中值当参数传入
fn(*d) # 等于d.keys()
def fn(**kwargs):
    for k, v in kwargs.items():
        print(k, v)


d = {"a": 1, "b": 2, "c": 3}
fn(**d)