song1002  

函数

【一】函数的定义

  • 函数的定义就相当于事先将函数体代码保存起来,然后将内存地址赋值给函数名,函数名就是对这段代码的引用,这和变量的定义是相似的。

函数的语法

def 函数名(参数1,参数2,...):
	函数体
	return 值
  • def: 定义函数的关键字;

  • 函数名:函数名指向函数内存地址,是对函数体代码的引用。函数的命名应该反映出函数的功能;

  • 括号:括号内定义参数,参数是可有可无的,且无需指定参数的类型;

  • 冒号:括号后要加冒号,然后在下一行开始缩进编写函数体的代码;

  • 函数体:由语句和表达式组成;

  • return 值:定义函数的返回值,return是可有可无的。

【1】无参无返回值

def sss():
    user=input('user>>: ').strip()
    pwd=input('password>>: ').strip()

【2】有参无返回值

  • 参数是函数的调用者向函数体传值的媒介
def greet(name):
    print(f"Hello, {name}!")


greet("Dream")  # Output: Hello, Dream!

def add_numbers(a, b):
    result = a + b
    print(f"The sum of {a} and {b} is {result}")


add_numbers(3, 5)  # Output: The sum of 3 and 5 is 8

【3】有参有返回值

# 定义一个函数,函数有两个参数
def add_numbers(a, b):
    result = a + b
    print(f"The sum of {a} and {b} is {result}")
    # 使用 return 关键字将想要返回的结果返回出去
    return result


res = add_numbers(3, 5)  # Output: The sum of 3 and 5 is 8
print(res) # 8

def rectangle_info(length, width):
    area = length * width
    perimeter = 2 * (length + width)
    return area, perimeter

# 解压赋值
area, perimeter = rectangle_info(4, 5)
print(f"Area: {area}, Perimeter: {perimeter}")
# Area: 20, Perimeter: 18

【二】函数三种调用方式

【1】直接调用

函数名() ---> 调用函数
def add(x, y):
    return x + y


# 直接调用函数,拿到对应的结果
result = add(3, 5)
print(result)  # 8

【2】表达式调用

def subtract(x, y):
    return x - y


# 将定义好的函数地址给对应的变量
operation = subtract
# 通过给定的变量进行调用
result = operation(10, 5)
print(result) # 5


【3】函数作为参数

# 【3】触发这个函数 带入参数x 参数y
def multiply(x, y):
    # 计算出返回值
    return x * y


def operate(func, x, y):
    # 【2】函数地址传过来 带参数过来 
    # 返回值是 函数地址(参数x,参数y)
    # 【4】接收到返回值并返回
    return func(x, y)


# 【1】operate 函数 有3个参数 : 函数地址 参数x 参数y
result = operate(multiply, 4, 6)
# 【5】拿到返回值
print(result)

【三】函数的参数

【1】形参和实参

  • 函数的参数分为形式参数和实际参数,简称形参和实参
    • 形参即在定义函数时,括号内声明的参数。
      • 形参本质就是一个变量名,用来接收外部传来的值。
    • 实参即在调用函数时,括号内传入的值
      • 值可以是常量、变量、表达式或三者的组合:
def add(x, y):
    return x + y


# 1:实参是常量
res_first = add(1, 2)
print(res_first)  # 3

# 2:实参是变量
x = 5
y = 6
res_second = add(x, y)
print(res_second)  # 11

# 3:实参是表达式
res_third = add(10 * 2, 10 * add(3, 4))
print(res_third)  # 90

# 4:实参可以是常量、变量、表达式的任意组合
a = 2
res_forth = add(a, 10 * add(3, 4))
print(res_forth)  # 72

【2】位置传参

  • 位置即顺序,位置参数指的是按顺序定义的参数

有位置参数而不传值会报错*

# 定义位置形参:name,age,sex,三者都必须被传值
def register(name, age, sex):
    print('Name:%s Age:%s Sex:%s' % (name, age, sex))


register()  # TypeError:缺少3个位置参数
'''
Traceback (most recent call last):
  File "E:\PythonProjects\01.py", line 175, in <module>
    register()  # TypeError:缺少3个位置参数
TypeError: register() missing 3 required positional arguments: 'name', 'age', and 'sex'
'''

不按位置传参会导致变量错误

# 定义位置形参:name,age,sex,三者都必须被传值
def register(name, age, sex):
    print('Name:%s Age:%s Sex:%s' % (name, age, sex))


register(18, "男", "Dream")
# Name:18 Age:男 Sex:Dream

【3】关键字传参

在调用函数时,实参可以是key=value的形式,称为关键字参数

# 定义位置形参:name,age,sex,三者都必须被传值
def register(name, age, sex):
    print('Name:%s Age:%s Sex:%s' % (name, age, sex))


# 根据指定关键字进行传参,不能多传参数,也不能少传参数
register(name="Dream", age=18, sex="男")
# Name:Dream Age:18 Sex:男



# 定义位置形参:name,age,sex,三者都必须被传值
def register(name, age, sex):
    print('Name:%s Age:%s Sex:%s' % (name, age, sex))


# 根据指定关键字进行传参,可以不按顺序传参
register(sex="男", name="Dream", age=18)
# Name:Dream Age:18 Sex:男

【4】位置和关键字传参数

但必须保证关键字参数在位置参数后面,且不可以对一个形参重复赋值

# 定义位置形参:name,age,sex,三者都必须被传值
def register(name, age, sex):
    print('Name:%s Age:%s Sex:%s' % (name, age, sex))


# 可以使用关键字和位置参数混合传参,但是一定要位置参数在前,关键字参数在后
register("Dream", age=18, sex="男")

# Name:Dream Age:18 Sex:男

【5】默认参数

在函数定义阶段的时候定义在函数名后面的 () 里面的参数可以给默认值位置参数给了默认值之后 在函数调用时,可以不指定默认参数的值,不给值默认就是默认值如果给了新值就会被新值覆盖掉

def student(name, gender='male'):
    print(f' my name is {name} my gender is {gender}')

#给了name但是没给 gender , gender使用的就是默认的值 male
student('dream')
# 寄给name有给gender , 给了 新值则覆盖掉默认值
student('dream',gender='other')
'''
# num_list 可变数据类型 ---> 定义一次下一次修改列表会影响到原来列表
def app_list(num, num_list=[]):
    num_list.append(num)
    print(num_list)
app_list(1)
app_list(2)
app_list(3)
[1,2,3]

# num_list 每一次调用函数都是一个新的列表所以值只会是最后一个
def app_list(num):
    num_list = []
    num_list.append(num)
    print(num_list)
app_list(1)
app_list(2)
app_list(3)
[3]


num_list = []
def app_list(num):
    global num_list
    num_list = []
    num_list.append(num)
app_list(1)
app_list(2)
app_list(3)
print(num_list)

【6】可变长参数

参数的长度可变指的是在调用函数时,实参的个数可以不固定

  • 而在调用函数时,实参的定义无非是按位置或者按关键字两种形式

[1]*args

任意类型参数

  • 如果在最后一个形参名前加 * 号,那么在调用函数时,溢出的位置实参,都会被 * 接收,以元组的形式保存下来赋值给该形参
# 在最后一个形参名args前加*号
def foo(x, y, z=1, *args):
    print(x)
    print(y)
    print(z)
    print(args)


foo(1, 2, 3, 4, 5, 6, 7)
# 实参1、2、3按位置为形参x、y、z赋值
# 多余的位置实参4、5、6、7都被*接收,以元组的形式保存下来,赋值给args
# 即args=(4, 5, 6,7)
  • 如果形参为常规的参数(位置或默认),实参仍可以是 * 的形式
def foo(x, y, z=3):
    print(x)
    print(y)
    print(z)


foo(*[1, 2])  # 等同于foo(1,2)

解包

def foo(x, y, *args):
    print(x)
    print(y)
    print(args)


L = [3, 4, 5]
foo(1, 2, *L)
# *L就相当于位置参数3,4,5 ----> 解包
# 对应到函数中就是,foo(1,2,*L)就等同于foo(1,2,3,4,5)

如果在传入 L 时没有加 * ,那 L 就只是一个普通的位置参数了

def foo(x, y, *args):
    print(x)
    print(y)
    print(args)


L = [3, 4, 5]
foo(1, 2, L)
# 如果在传入 L 时没有加 `*` ,那 L 就只是一个普通的位置参数了
# ([3, 4, 5],)

[2]*kwargs

  • 如果在最后一个形参名前加**号,那么在调用函数时,溢出的关键字参数,都会被 ** 接收,以字典的形式保存下来赋值给该形参
def foo(x, **kwargs):  # 在最后一个参数kwargs前加**
    print(x)
    print(kwargs)


foo(y=2, x=1, z=3)
# 溢出的关键字实参y=2,z=3都被**接收,以字典的形式保存下来,赋值给kwargs
# 1
# {'y': 2, 'z': 3}
  • 如果我们事先生成了一个字典,仍然是可以传值给 **kwargs
ef foo(x, y, **kwargs):
    print(x)
    print(y)
    print(kwargs)


dic = {'a': 1, 'b': 2}
foo(1, 2, **dic)
# **dic就相当于关键字参数a=1,b=2,foo(1,2,**dic)
# 等同foo(1,2,a=1,b=2)

# 1
# 2
# {'a': 1, 'b': 2}
  • 如果形参为常规参数(位置或默认),实参仍可以是 ** 的形式
ef foo(x, y, z=3):
    print(x)
    print(y)
    print(z)


foo(**{'x': 1, 'y': 2})  # 等同于foo(y=2,x=1)

【7】命名关键字参数

需要在定义形参时,用 * 作为一个分隔符号,* 号之后的形参称为命名关键字参数

def register(name, age, *, sex, height):  # sex,height为命名关键字参数
    pass


# 正确使用
register('Dream', 18, sex='male', height='1.8m')

# TypeError:未使用关键字的形式为sex和height传值
register('Dream', 18, 'male', '1.8m')

# TypeError没有为命名关键字参数height传值。
register('Dream', 18, height='1.8m')

【8】混合使用

  • 综上所述所有参数可任意组合使用,但定义顺序必须是:
    • 位置参数、默认参数、*args 、命名关键字参数、***kwargs
  • 可变参数args与关键字参数*kwargs通常是组合在一起使用的
  • 如果一个函数的形参为 **args**kwargs,那么代表该函数可以接收任何形式、任意长度的参数
  • 所有位置参数、默认参数、*args 、**kwargs 混合使用的时候不允许使用关键字参数
  • 所有位置参数、默认参数、*args 、**kwargs **** kwargs 必须在 *args 之后
posted on 2024-04-15 21:36  嘉峪关吴彦祖  阅读(2)  评论(0编辑  收藏  举报