随笔 - 65  文章 - 0 评论 - 0 阅读 - 28638
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

 一 基本声明

函数声明语法

def 函数名(参数列表):
    '''
    # 函数文档
    params:
    return:
    '''
    # 实现特定功能的多行代码
    [return [返回值]]

函数调用语法

函数名()

查看说明文档

方式一:
print(函数名.__doc__)
方式二:
help(函数名)

二 函数参数

函数参数 实例
形参和实参
def add(x, y):  # 声明的参数称之为形式参数,简称形参
print(x + y)


test = (3, 4)
add(*test) #将调用过程中传入的值称之为实际参数,简称实参
位置参数

def add(x,y): # x,y是形参,用来接收实参

print(x+y)

add(2,3) # 2,3 是实际参数,分别传递给形参x,y

 
默认参数 def print_stu_info(name,age,gender="male"):

print("学员姓名:",name)
print("学员年龄:",age)
print("学员性别:",gender)

print_stu_info("张三",23)

#有默认值的参数必须位于所有没默认值参数的后面,否则报错!

关键字参数

def print_stu_info(name,age,height,weight,job):

print("学员姓名:",name)
print("学员年龄:",age)
print("学员身高:",height)
print("学员体重:",weight)
print("学员工作:",job)

print_stu_info("张三",height="180cm",weight="90kg",job="销售",age=23)

#使用位置参数和关键字参数混合传参的方式。但需要注意,混合传参时关键字参数必须位于所有的位置参数之后。

不定长参数

def print_stu_info(name, age=18, *args, **kwargs):
print(name, age)
print(args)
print(kwargs)

print_stu_info("小红", 20, "China", "Beijing", height="188cm", weight="60kg")

#虽然有了不定长实参,但是如果函数声明时,使用的是位置形参,则不定长实参的数量一定要和位置形参的数量对应!!

注:

1 不定长参数

(1)在工作中,有时候就会有些函数,就要接收个数不确定的参数。这时候,都可以使用不定长参数来完成。
不定长参数有2种写法:
1. 在形参的位置参数左边使用*表示,接收0~多个位置实参,这种情况下,*号左边的形参,在函数内部就是一个元组。在函数定义中使用*args传递非命名键值可变长参数列表
2. 在形参的位置参数左边使用**表示,接收0~多个关键字参数,这种情况下,**号左边的形参,在函数内部就是一个字典。在函数定义中使用**kwargs传递键值可变长参数列表

(2)有了不定长形参以后,也可以在形参中继续使用位置参数和默认参数

形参的书写顺序:位置形参 > 默认形参 > 元组不定长形参 > 字典不定长形参

(3)可以使用*号把元组,列表,打散成位置实参,也可以使用**号把字典打散成关键字实参
复制代码
"""
调用函数时,我们如果参数较多,可以使用不定长实参:
可以使用*号把元组,列表,打散成位置实参
也可以使用**号把字典打散成关键字实参
"""
student_list = [
    {"name":"小名", "age": 17, "sex": True, "mobile": "1331234567"},
    {"name":"小白", "age": 27, "sex": False, "mobile": "1361234567"},
]

def func3(name, age, mobile, sex=False):
    """打印学生信息"""
    print(f"name={name}")
    print(f"age={age}")
    print(f"sex={sex}")
    print(f"mobile={mobile}")

# # 打印小白的信息
# func3(student_list[1]["name"], student_list[1]["age"], student_list[1]["mobile"])
#
# # 上一行代码,太长了,针对上面的代码,其实就是把字典中所有的数据传递给函数内部
# stu = student_list[1]
# func3(name=stu["name"], age=stu["age"], mobile=stu["mobile"])

# 使用**打散,可以让上面代码可以缩写成一句
# stu = student_list[1]
# func3(**stu) # 就是上面代码的简写 func3(name=stu["name"], age=stu["age"], mobile=stu["mobile"])
复制代码

三 函数返回值

我们希望把函数内部产生的一些数据或者结构返回给调用处,那么可以使用return关键字返回值。如果没有return语句或者return后没有具体值,都默认返回None。
特殊的常量 None(N 必须大写)。和 False 不同,它不表示 0,也不表示空字符串,而表示没有值,也就是空值
函数的结果,可以没有,也可以有一个或者多个,但是return只能执行一次,且执行到了return,则表示当前函数已经执行结束了,后续代码将不会被执行
def func2(x, y):
    ret1 = x + y
    ret2 = x - y
    return ret1, ret2  # 可以通过组包的方式,把函数中数据,变量,返回给外界调用处。


a, b = func2(1, 2).  # 3 -1  #使用=号在函数调用的左边声明变量来接收函数的返回值
注:在使用python的内置函数或者其他人声明的函数,要知道它是否有结果,可以通过pycharm提供的查看函数的说明文档来了解。

在函数说明文档中,如果没有发现 -> 或者 出现 ->None 的都表示当前函数没有返回结果,没有返回结果就不需要在调用函数时使用=号和变量接受结果了。

四 函数作用域

  1 函数嵌套:函数内部声明一些函数,这些函数,在函数的外界无法使用。

2 作用域:变量的有效范围。变量在python代码执行过程中,该变量的使用范围和生命周期

3 LEGB:根据变量声明的位置和使用的位置,分函数外和函数内,文件外和文件内,有以下4种不同的作用域级别

因为作用域的问题,所以按不同作用域可以把变量划分为2种:局部变量与全局变量。

  • 局部变量,函数内部声明的变量。默认情况下,只有在函数运行时局部变量才会出现在内存中,当函数执行结束,内存中的局部变量就会被销毁,所以局部变量无法被当前函数以外的地方使用

  • 全局变量,函数外部声明的变量,或者在函数内部global显式声明为全局变量。默认在任意位置都可以使用,从被声明的位置开始,直到程序结束或者被del关键字删除。

 实例:

复制代码
函数内部的局部变量如果与函数外部的全局变量的名字一样,则优先使用局部变量
"""函数在有需要的情况下,也可以声明全局变量或者在同名情况下设置优先调用全局变量"""
num = 10  # 全局变量,所在的作用域是全局作用域
def func1():
    # 通过global关键字,可以设置函数内部的1个或多个变量为全局变量
    # global 变量1,变量2,.....

    global num  # 通过global关键字,让当前函数使用变量num时,调用全局作用域下的num
    num = 20

func1()
print(num)  # 20
"""
在嵌套函数的时候,就会存在嵌套作用域
"""
"""
情况1:在函数内部,如果没有对应的变量名,则函数内部会往函数外部,查找对应的变量,当找到以后,直接调用。找不到再报错。
"""
# num = 10 # 函数外,属于全局作用域
# def func1():
#     print(f"func1, num={num}")  #func1, num=10    # 嵌套函数的外部,属于func2的嵌套作用域
#     def func2():
#         print(f"func2, num={num}")  # func2, num=10 # 函数内部,属于func2的局部作用域
#     func2()
# func1()
# print(f"函数外, num={num}") # 函数外, num=10
"""
情况2:当函数内部存在变量赋值语句,则函数内部如果没有global或者nolocal关键字,则表示在函数内部声明一个局部变量。
该变量,可以被当前作用域下的后续代码调用,也可以被嵌套函数内部(子作用域)调用。
"""
# num = 10  # 函数外,属于全局作用域
# def func1():
#     num = 20  # 此处,是赋值语句,因为当前函数没有出现global或nolocal关键字
#     print(f"func1, num={num}")  # func1, num=20      # 嵌套函数的外部,属于num的本地作用域
#     def func2():
#         print(f"func2, num={num}")  # func2, num=20  # func2是func1的子作用域,func1是func2的父作用域
#     func2()
# func1()
# print(f"函数外, num={num}")  # 函数外, num=10
总结:
在函数嵌套过程中,每次嵌套都会产生一个新的嵌套作用域,包含的作用域就产生了父作用域和子作用域的情况。
子作用域下的局部变量无法被父作用域使用。
子作用域要调用父作用域的变量,则可以通过nolocal关键字调用
子作用域要调用全局作用域的变量,则可以通过global关键字来调用
# a = 10
# b = 20
# c = 30
# def func1():
#     c = 40
#     d = 50
#     e = 100
#     print(f"func1,a={a}")     # func1,a=10
#     def func2():
#         global c  # 获取顶级作用域下的c
#         print(f"func2,b={b}")  # func2,b=20
#         print(f"func2,c={c}")  # func2,c=30,global直接让变量指向到了函数外全局作用域的全局变量,跳过了父作用域
#     func2()
#     def func3():
#         # nolocal表示接下来,进行赋值操作的变量不是在当前作用域下创建局部变量,而是调用来自父级作用域下的变量
#         # nonlocal 变量1,变量2,....
#         nonlocal d
#         d = 60  # 赋值语句
#         print(f"func3,b={b}")  # func3,b=20
#         print(f"func3,c={c}")  # func3,c=40
#         print(f"func3,d={d}")  # func3,d=60
#         e = 200 # 此处的赋值语句,因为在函数func3中没有表示当前e是属于父作用域或全局作用域的,因此这个就是声明局部变量
#         print(f"func3,e={e}")  # func3,e=200
#     func3()
#     print(f"func1, d={d}") # func1, d=60  # func3中的修改d的时候设置nolocal,所以d就是func3的父作用域func1的变量d了
#     print(f"func1, e={e}") # func1, e=100,func3中的局部改了,对于外界是不影响的。
# func1()
"""
内置作用域,其实就是文件模块以外,由python解释器内置的变量命名空间。
在任意位置执行访问都可以得到内置作用域的变量,但是当全局作用域下或局部作用域下,出现同名赋值,则相当于创建一个当前作用域的变量。
但是其他python文件中,依然可使用内置作用域下的变量。
"""
# print(max)  # <built-in function max>
# max = 10
# print(max)  # 10
复制代码

五 匿名函数

定义:也叫 lambda 表达式。就是简单函数(函数体仅是单行的表达式)的简写版本。相比函数,lambda 表达式具有以下 2 个优势:

  • 对于单行函数,使用 lambda 表达式可以省去定义函数的过程,让代码更加简洁;

  • 对于不需要多次复用的函数,使用 lambda 表达式可以在用完之后立即释放,提高程序执行的性能。

语法格式:

复制代码
 1 格式1:
 2     变量 = lambda 参数列表: 返回结果
 3 格式2:
 4     lambda 参数列表: 返回结果
 5 
 6 """
 7 # 格式1:
 8 # add = lambda x,y: x + y
 9 # ret = add(10,20)
10 # print(ret)
11 
12 # 格式2:
13 # ret = (lambda x, y: x + y)(10,20) # 声明匿名函数的同时,直接调用了
14 # print(ret)
复制代码

实例:

复制代码
"""lambda在工作中也是比较常用,一般有如下集中情况:"""
"""1. 列表排序"""
# data1 = [11, 2, 20, 21, 3, "5", "10"]
# # 方式1:
# # key参数可以指定列表在排序时,前后两个成员比较大小时的代码段
# # def func(a):
# #     return int(a)
# # data1.sort(key=func)
# # 方式2:上面的代码就可以使用lambda简写了
# data1.sort(key=lambda x: int(x))
# print(data1) # [2, 3, '5', '10', 11, 20, 21]

"""
 声明一个函数,就需要在内存中保存这段代码,肯定会需要额外的内存空间。
 声明一个匿名函数,则传入到函数内部时,才会在存在出现,在函数执行以后,这个匿名函数就会被内存空间回收(销毁了,删除了)
"""

"""2. 字典排序"""
# data2 = {"name": "小名", "age": 18, "money": 30.00, "mobile": "13312345678"}
# data3 = [
#     {"name":"商品1", "price": 30.00},
#     {"name":"商品2", "price": 55.00},
#     {"name":"商品3", "price": 19.00},
#     {"name":"商品4", "price": 9.90},
# ]
# # def func(x):
# #     return x["price"]  #取key=price的value值
# data3.sort(key=lambda x: x["price"])  # 从小到大
# data3.sort(key=lambda x: x["price"], reverse=True) # 从大到小
# print(data3)

"""3. 作为参数传递到另一个函数中使用"""


# 四则运算(加减乘除)的计算机
def calc(x, y, o):
    """计算器,完成2个数字的运算"""
    print("记录操作过程。。。。")
    ret = o(x, y)
    print("记录操作结果。。。。")
    return ret


ret = calc(10, 20, lambda x, y: x + y) #等同于(lambda x, y: x + y)(10,20)  #lambda:匿名函数,x,y:形参,x+y:函数里的表达式,(10,20):实参
print(ret) 
复制代码

六 函数名的使用

整数、浮点数、字符串、列表、字典、元组、函数、类本身、类型本身以及模块等都是对象。

因为都是对象,所以 Python 中的函数才和整数、字符串、列表、字典和元组等对象的地位是平等的,成为了“一等公民”。python中函数与其他数据类型一样同属于一等公民(first-class elements,也叫一等对象)。

“一等公民”是指代满足下述条件的程序实体:
1、可赋值给变量,让变量代表它运行。 变量=xxx
2、可作为函数的参数。 函数名(xxx)
3、可作为函数结果返回。 return xxx
4、可包含在数据结构中,例如可以包含在列表等数据类型中作为成员存在。 {"a":xxx}

复制代码
# 也可以作为复合数据类型的成员值存在
data = {
    "+": lambda x, y: x + y,
    "-": lambda x, y: x - y,
    "*": lambda x, y: x * y,
    "/": lambda x, y: x / y,
}

print(data["+"])  # <function <lambda> at 0x000001FECE5DA670>
print(data["+"](10, 20))  # 30
复制代码

 

 





posted on   大明花花  阅读(260)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
点击右上角即可分享
微信分享提示