第三周周测
1.函数参数的两⼤⼤分类及两者关系
- 分类
- 形参
- 形式参数是在函数定义时声明的变量,用于接收调用该函数时传入的实际参数的值
- 实参
- 实际参数是在函数调用时传递给函数的具体数值或变量。
- 形参
- 关系
- 当函数被调用时,实际参数的值会被赋值给相应的形式参数,然后函数使用这些形式参数进行计算和操作。
2.阐述函数参数的种类及各⾃特征
- 函数参数的种类
-
默认参数
- 在函数定义时指定默认值的参数,如果函数调用时没有传入该参数,将使用默认值。
- 默认参数必须在位置参数后面定义,否则会产生语法错误。
-
关键字参数
- 使用形如“key=value”的语法来指定参数,可以不按照定义顺序传递参数。
- 如果一个函数同时接收位置和关键字参数,位置参数必须在关键字参数之前传递。
-
位置参数
- 按照定义顺序传递给函数的参数,是最常见的参数类型。
- 函数调用时必须提供该参数,否则会抛出异常。
-
*args
- 使用星号(*)作为前缀,在函数定义时接受任意数量的位置参数,以元组的形式传递给函数。
- 调用时可以传递任意数量的位置参数。
-
**kwargs
- 使用两个星号(**)作为前缀,在函数定义时接受任意数量的关键字参数,以字典的形式传递给函数。
- 调用时可以传递任意数量的关键字参数。
-
3.什么是名称空间,有哪些种类,查找顺序如何确定
-
什么是名称空间
- 名称空间是一个用于存储变量名与具体对象之间关系的数据结构。
- 它允许在程序中使用相同名称但指向不同对象的变量。
-
分类
- 全局名称空间(global namespace)
- 包含程序中定义的全局变量和函数的名称。
- 内置名称空间(built-in namespace)
- 包含所有内置函数和异常的名称。
- 本地名称空间(local namespace)
- 在函数调用时创建,包含函数参数和在函数内部定义的局部变量。
- 全局名称空间(global namespace)
-
查找顺序
- 由 LEGB 规则决定,即从当前作用域开始依次向上查找,直到找到第一个匹配的名称为止。
- LEGB 是指 Local、Enclosing、Global 和 Built-in 四个作用域,按照这个顺序逐级往上搜索,直到找到符合条件的变量或者抵达最外层作用域。
4.关键字global与nonlocal的作⽤
-
global
- 用于在函数内部访问并修改全局变量,即在函数内部将一个变量声明为 global 后,对该变量的修改将影响到全局作用域中的变量。
x = 1 def func(): global x x = 2 func() print(x) # 输出 2
-
nonlocal
- 用于在嵌套函数中访问并修改外层函数的变量,即在内层函数中将一个变量声明为 nonlocal 后,对该变量的修改将影响到外层函数作用域中的变量。
def outer(): x = 1 def inner(): nonlocal x x = 2 inner() print(x) # 输出 2 outer()
5.函数名的使⽤⽅法有哪些
- 函数名的使用方法
- 定义函数:
- 使用函数名来创建一个新的函数,指定函数的名称、输入参数和输出结果等信息,以便在程序中调用该函数。
- 调用函数:
- 使用函数名来调用已经定义好的函数,传递需要处理的输入参数,并获取函数返回的计算结果。
- 作为参数传递:
- 将函数名作为参数传递给另一个函数或方法,使得该函数或方法可以调用所传递的函数进行特定的计算操作。
- 作为返回值返回:
- 函数名也可以作为另一个函数的返回值返回,从而实现一些高级编程技巧,如函数式编程或装饰器模式。
- 作为对象属性访问:
- 在某些面向对象编程语言中,函数名也可以作为对象的属性之一,通过对象引用获取该函数并调用。
- 定义函数:
6.什么是闭包函数,有何实际应⽤
- 闭包函数
- 指在函数内部定义的函数,它可以访问和修改其外部函数的变量,并且在外部函数执行完毕后仍然可以保持对这些变量的引用。
- 实际应用
- 闭包函数通常用于需要记住状态或者保存上下文信息的场景中
- 例如
- 事件处理器
- 回调函数等。
7.什么是装饰器,你能详细说说装饰器的推导流程吗
-
什么是装饰器
- 在不修改函数源代码的情况下,动态的增强或者修改函数的行为。
-
推导流程
- 定义一个装饰器函数,该函数接收一个函数作为参数,并返回一个新的函数。
- 在新的函数中使用原始函数并添加额外的逻辑。
- 将新的函数返回作为原始函数的替代品。
def my_decorator(func): def wrapper(): print("Starting the function...") func() print("Function completed.") return wrapper @my_decorator def my_function(): print("Hello, world!") my_function()
- 这个装饰器定义了一个名为
my_decorator
的函数,它接收一个函数作为参数。 - 在函数内部,它定义了一个新的函数
wrapper
,该函数在调用原始函数之前和之后输出一些信息。 - 最后,装饰器返回
wrapper
函数,并通过@my_decorator
这个语法糖来应用装饰器到my_function
上。 - 运行
my_function()
时,将会依次输出 "Starting the function..."、"Hello, world!" 和 "Function completed."。
8.⼿写装饰器模板(普通+修复+有参)
-
普通装饰器
def decorator(func): def wrapper(*args, **kwargs): # 对函数进行装饰 return func(*args, **kwargs) return wrapper @decorator def my_function(): pass
-
修复技术
from functools import wraps def decorator(func): @wraps(func) def wrapper(*args, **kwargs): # 对函数进行装饰 return func(*args, **kwargs) return wrapper @decorator def my_function(): pass
-
有参装饰器
def decorator_with_args(arg1, arg2): def decorator(func): def wrapper(*args, **kwargs): # 对函数进行装饰,使用arg1和arg2 return func(*args, **kwargs) return wrapper return decorator @decorator_with_args(arg1, arg2) def my_function(): pass
9.装饰器语法糖作⽤机理
- 什么是装饰器语法糖
- 装饰器语法糖是一种Python编程语言特性
- 它允许开发者在不修改原始函数代码的情况下
- 通过在函数定义之前加上一个修饰器函数
- 改变函数的行为或添加额外的功能。
- 当一个函数被修饰器修饰后,在调用该函数时
- 实际上是调用了修饰器返回的新函数。
- 这个新函数可以包装原始函数,添加额外的逻辑或修改输入和输出等行为。
- 装饰器使得代码更加简洁,易于维护和重用。
- 装饰器语法糖是一种Python编程语言特性
- 装饰器语法糖的作用机理
-
基于Python中函数也是对象的概念。
- 因为函数本质上是对象
- 所以可以将一个函数作为参数传递给另一个函数
- 并在另一个函数内对其进行修改或包装
- 最后返回修改后的函数。
-
这种使用函数作为参数并返回函数的编程技巧称为高阶函数。
-
装饰器利用了高阶函数的思想,使得开发者能够更加方便地对函数进行扩展和修改。
-
10.什么是递归函数,python默认最⼤递归深度
-
什么是递归函数
- 递归函数是调用自身的函数。
-
在Python中,当一个函数调用自身时就会产生递归。
- Python默认的最大递归深度为1000
- 在达到这个深度之后,程序会抛出RecursionError异常。
- 可以使用sys模块中的setrecursionlimit()方法来增加最大递归深度
- 但需要注意过多地增加深度可能会导致程序栈溢出或其他问题。
- Python默认的最大递归深度为1000
11.⼿写出⼆分法伪代码
1. 将数组按升序排列
2. 定义变量 left = 0 和 right = 数组长度 - 1
3. 当 left <= right 时,执行以下步骤:
a. 将中间元素的下标 mid = (left + right) / 2 取整
b. 如果目标值等于数组中的中间元素,则返回 mid
c. 如果目标值小于中间元素,则将 right 更新为 mid - 1
d. 如果目标值大于中间元素,则将 left 更新为 mid + 1
4. 目标值不存在于数组中,返回 -1
def half_sort(l, search_num):
l.sort()
num = round(len(l) / 2)
if len(l) == 1:
print(l[0])
else:
if search_num in l[:num]:
l_left = l[0:num]
print(l_left)
half_sort(l_left, search_num)
else:
l_right = l[num:]
print(l_right)
half_sort(l_right, search_num)
12.什么是匿名函数,主要配置哪些函数⼀起使⽤,各⾃有何特征
-
什么是匿名函数
- 匿名函数是一种没有名称的函数,通常在需要临时定义和执行某些逻辑的情况下使用。
- 主要配置与之搭配使用的函数有高阶函数和Lambda函数。
lambda x:x*2 lambda 返回值:函数表达式
-
主要配置的函数
-
map
- 映射函数
- map(参数,匿名函数)
numbers = [1, 2, 3, 4, 5] squared_numbers = list(map(lambda x: x**2, numbers)) print(squared_numbers) # [1, 4, 9, 16, 25]
-
filter
- 过滤函数,过滤条件为True的变量
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] # 过滤出所有偶数 even_numbers = list(filter(lambda x: x % 2 == 0, numbers)) print(even_numbers) # 输出:[2, 4, 6, 8, 10]
-
-
匿名函数的特征
- 没有名称,只能通过变量引用或作为参数传递使用。
- 可以有多个参数,但通常只包含一个表达式。
- 通常用于简单的逻辑,例如过滤列表或映射元素。
13.什么是可迭代对象、迭代器对象,两者有何关系
- 什么是可迭代对象
- 可迭代对象就是具有
__iter__()
方法的对象 - 可迭代对象是指可以使用for循环遍历的对象,例如列表、元组、字典、集合等。
- 可迭代对象就是具有
- 迭代器对象
- 迭代器对象就是具有
__iter__()
和__next__()
方法的对象 - 迭代器对象
- 是指可以按照一定顺序逐个访问元素的对象
- 通过调用其 next() 方法来实现。
- 每次调用 next() 方法时,迭代器会返回下一个元素
- 当没有元素可以返回时,会抛出 StopIteration 异常。
- 通常情况下,一个可迭代对象能够产生一个迭代器对象。
- 迭代器对象就是具有
- 关系
- 迭代器对象一定是可迭代对象,可迭代对象不一定是迭代器对象
- 所有迭代器对象都是可迭代对象,但并非所有可迭代对象都是迭代器对象。
- 可迭代对象只有在被for循环或者手动转化成迭代器对象后才能逐个访问元素。
14.什么是异常、程序中如何解决异常、异常处理的完整结构是怎样的
-
什么是异常
- 异常是程序执行时出现的错误或意外情况
-
程序中如何解决异常
- 利用 try .. except .. 方法 捕获异常并抛出异常
-
异常处理的完整结构
try: print() except Exception as e: print("Error: " + str(e))
- 可以配合else使用
- 发生错误则继续走else
try: print('111') except Exception as e: print("Error: " + str(e)) else: print("222")
- 可以配合finally使用
- 发布发生错误都会走finally
try: print('111') except Exception as e: print("Error: " + str(e)) else: print("222") finally: print('333')
- 可以配合else使用
【一】代码实战之装饰器计数
【1】需求
'''
1.编写统计函数执⾏次数装饰器
任意定义⼀个函数给其添加装饰器
要求:
每次执⾏该函数 装饰器⾃动记录次数 记录需保存在⽂件中
'''
【2】代码
# -*-coding: Utf-8 -*-
# @File : works_system .py
# author: Chimengmeng
# blog_url : https://www.cnblogs.com/dream-ze/
# Time:2023/6/3
# 导入OS模块 ---> 用来创建文件,数据库位置
import os
# 装饰器修复技术所需要的模块 ---> 修复装饰器
from functools import wraps
# 定义装饰器函数 -- 外部函数
def func_counter(func):
# 声明数据库位置 ---> 存储到 txt 文件中
counts_file = 'func_counts.txt'
# 进行数据文件位置的判断 ---> 如果存在这个文件则忽略,如果不存在这个文件则新建
if not os.path.exists(counts_file):
# 创建文件并打开文件进行第一次写入 ---> 执行次数为1
with open(counts_file, 'w') as f:
f.write('1')
count = 1
else:
# 已经存在数据库位置文件 ---> 里面的数据至少为 1
# 打开数据库文件进行读取数据
with open(counts_file, 'r+') as f:
# 将拿到的数据(字符串数据) ---> 转为整型并 次数 +1
count = int(f.read()) + 1
# 将光标移动到首字符的位置,否则光标实在上一个字符的后边,造成字符追加的效果
f.seek(0)
# 写入数据(覆盖数据)
f.write(str(count))
# 定义装饰器内部函数
@wraps(func) # 装饰器的修复技术
def wrapper(*args, **kwargs):
# 这里拿到外部调用函数的返回值
result = func(*args, **kwargs)
# 返回这个调用函数的返回值
return result
# 统计一共运行了多少次
print(f'执行程序一共运行了::>>{count}次!')
# 返回内部的函数的内存地址
return wrapper
# 语法糖进行装饰
@func_counter
def my_function():
print('这是执行函数')
# 调用函数
my_function()
【二】代码实战之员工管理系统
【1】需求
2. 编写员⼯管理系统进阶版
功能全部封装成函数 数据全部来源于⽂件
⼤致功能:注册 登录 添加员⼯ 查看指定员⼯ 查看全体员⼯姓
名等
普通要求:
添加 查看等功能每次都必须先登录才可执⾏(认证装饰器)
进阶要求:
⽤户登录⼀次之后⽆⽆需校验身份(全局校验)
升华超越(选做题):
每个⽤户配备⻆⾊信息
⽤户认证过程中只有管理员才可执⾏被装饰函数