函数

定义语法

# Python 3.5 之前
def 函数名(参数):  # 参数可选
  执行代码  
  执行代码  # 同样的缩进,表示一个代码块
  
# Python 3.5 之后可以约束函数入参和返回值类型
def 函数名(参数: 参数类型) -> 返回值类型:
  执行代码  
  执行代码  
  
# 调用函数
函数名(参数)

函数示例

# 3.5 之前
def myFunction():
    print("hello world!")

# 3.5 之前
def myFunction1(num):
    if num > 0:
        print("正数")
    else:
        print("负数")

# 3.5 之后可以对参数和返回值进行类型声明
def myFunction2(num: int) -> bool:
    if num <= 0:
        return False
    else:
        return True


myFunction()  # 输出 hello world!
myFunction1(1)  # 输出 正数
print(myFunction2(2))  # 输出 True

函数参数

位置参数

必传的参数就叫位置参数,形参和实参的对应关系是 按顺序对应

def add(a, b):
    return a + b

# 报错,因为 add 函数的参数是位置参数(必传的就叫位置参数)
add()

# 1 会传给 a,2 会传给 b
print(add(1, 2))  # 输出 3

关键字传参

自行决定实哪个形参接收传递的参数

def add(a, b):
    return a + b

# 1 会传给 b,2 会传给 a
print(add(b = 1, a = 2))

参数默认值

# 参数 c 不必传,如果不传就是 100
def sub(a, b, c = 100):
    c -= a + b
    return c

print(sub(10, 20))  # 输出 70,c 是 100
print(sub(10, 20, 200))  # 输出 170,c 是 200

可变参数

非字典类型。方法定义时,参数如果用 * 修饰,表示是可变参数

def add(*args):
    sum = 0
    print(type(args))  # 实际使用元组 tuple 来接收参数的
    if len(args) > 0:  # 布尔值会自动转型,所以这行可以简化为 if args: 
        for arg in args:  # 这是一个求和的循环,内置函数 sum(tuple) 可以直接求和
            sum += arg
    return sum

print(add())  # 输出 0
print(add(1, 2, 3))  # 输出 6

字典类型。方法定义时,参数如果是 ** ,表示要传一个字典(字典就不限制元素个数了,可变参数)

def add(**kwargs):
    print(type(kwargs))  # 实际也是使用 dict 来接收参数的
    for k, v in kwargs.items():  # 打印参数和值
        print(f"参数名称:{k},参数值:{v}")
    return sum(kwargs.values())  # dict.values 返回的是一个序列,直接使用 sum 函数来求和

print(add(a=1, b=2, c=3))  # 输出 6

控制台输出:

<class 'dict'>
参数名称:a,参数值:1
参数名称:b,参数值:2
参数名称:c,参数值:3
6

形参顺序

如果方法定义时,参数很多,有位置参数、默认值参数、可变参数等。定义是顺序是有要求的

位置参数 -> 默认值参数 -> 可变参数(非字典) -> 可变参数(字典)

def fun(a, b, c = 10, *args, **kwargs):

形参生命周期

python 是逐行解释来执行的,解释方法时,如果方法有参数,就会在内存开辟空间并和参数进行绑定(建立引用关系)

需要注意的是这个引用关系会一直存在,不会说方法调用结束而断开引用

下面这例子因为参数是列表,方法内在一直改变列表的值,所以随着方法多次调用,形参的值会一直变化

def test(a, list=[1, 2]):
    list.append(a)
    return list

# 输出 [1, 2, 3]。第一次调用,往 list 添加 3,所以输出 123
print(test(3))  

# 输出 [1, 2, 3, 4]。第二次调用,因为 list 现在已经是 123 了,所以这里添加 4 就是 1234
print(test(4))  

# 输出 [40, 50, 60]。传了一个新的列表进去,方法内会往这个新的列表添加值,所以是 40 50 60
print(test(60, [40, 50]))  

# 输出 [1, 2, 3, 4, 3]。这里没传列表,又会使用原来的列表,原来已经是 1234了,所以这里添加 3 就是 12343
print(test(3)) 

函数返回值

return 语句用户返回函数值,并且会退出函数

不使用 return 函数结束也有返回值,返回 None

# 函数自然结束,返回 None
def test():
    pass

# 函数什么都不返回,返回的也是 None
def test2():
    return  

# 返回 tuple
def test3(a, b):
  r1 = a**2
  r2 = b**2
  return r1, r2  # 封装成 tuple 返回(多个参数的返回值,默认会封装 tuple)
c = r1, r2 = test3(1, 2)
print(type(c))  # 输出 <class 'tuple'>

# 返回 list
def test3(a, b):
  r1 = a**2
  r2 = b**2
  return [r1, r2]  # 封装成 list 返回(这里必须用中括号,不然默认会封装成 tuple)
c = r1, r2 = test3(1, 2)  # 输出 <class 'list'>

# 其他类型就不举例了,str、dict、int、float 等直接返回就行了

全局和局部变量

分为全局变量和局部变量,方法内部定义的变量是局部变量,函数外面定义的是全局变量

函数内可以访问全局变量,函数外不能访问局部变量

当局部变量和全局变量同名时,在方法内部,局部变量更优先

a = 10  # 全局变量

def test():
    global a  # 声明在方法中,所有的 a 都会使用全局变量
    print(a + 10)  # 输出 20
    a += 20  # 改变全局变量的值为 30
    print(a)  # 输出 30


# 调用后会修改全局变量 a 的值,不调用就不修改
# test()

print(a)  # 输出 10
posted @ 2025-03-08 22:44  CyrusHuang  阅读(19)  评论(0)    收藏  举报