【嵌入式学习4】特殊参数、文件IO
目录
1、默认值参数、关键字参数
①默认值参数:形参设定默认值称为默认参数
②关键字参数:调用函数时,实参可以指定对应的形参,称为关键字参数
③默认值参数和关键字参数区别
④默认值参数和关键字参数例子
2、可变参数
①可变参数args
②可变参数kwargs
③传递元组/列表给可变参数args
④传递字典给可变参数kwargs
⑤组合使用
3、递归函数
递归含义:
递归的好处:
4、文件I/O
①打开文件
访问模式:
②关闭文件
③文件读取
④文件写入
⑤with使用
⑥绝对路径与相对路径
5、文件备份
1、默认值参数、关键字参数
①默认值参数:形参设定默认值称为默认参数
def say_hello(name='张三'):# 形参
print('hello ', name)
# 调用时不传递参数,使用默认值
say_hello()
# 调用时传递参数
say_hello('李四')
# 默认参数一定要在参数的最后
def say_hello(score, name='张三'):# 默认参数放在参数最后面
print('hello %s'%(name))
say_hello(60, '李四')
②关键字参数:调用函数时,实参可以指定对应的形参,称为关键字参数
def say_hello(name, age, score):
print('姓名:%s,年纪:%d,分数:%f'%(name,age,score))
say_hello(name='张三',age=60,score=70.5)
# 使用关键字参数调用可以传递参数的顺序
say_hello(score=70,age=30,name='李四')
③默认值参数和关键字参数区别
默认参数 | 关键字参数 | |
定义 | 在函数定义时,为某个参数指定一个默认值,如果调用参数时没有为该参数提供值,则使用默认值 | 在调用函数时,通过参数名指定参数值,而不是按照位置传递参数 |
作用 | 提供了一种方便的方式来处理可选参数。如果调用者不想为某个参数提供值,则可以使用默认值,从而使函数调用更加灵活 | 主要用于明确指定参数的名称,使代码更清晰易读,关键字参数可以与位置参数混合使用,但位置参数必须在关键字参数之前。 |
使用 | 适用于函数中某些参数有常见的默认值,调用者可以选择性提供这些参数,常用于配置函数的行为,如设置日志级别、超时时间等 | 当函数有多个参数且顺序易混淆时,使用关键字参数可提高代码的可读性和可维护性。适用于需要明确指定参数名称的情况,如调用库函数时,明确指定参数名称可以避免因库函数参数顺序变化而导致的错误。 |
注意 | 如果默认参数是可变对象(如列表、字典等),则每次调用函数时,如果没有提供该参数,会使用同一个对象,这可能导致意外。 为了避免这个问题,可以将默认值设置为 | 关键字参数不能在位置参数之前使用。例如,以下代码是错误的: 正确的调用方式是: |
④默认值参数和关键字参数例子
def create_user(self,username,passward,is_admin=False,is_active=True,is_verified=False):
# 创建用户的逻辑
print("Creating user...")
print("Username:", username)
print("Password:", password)
print("Is Admin:", is_admin)
print("Is Active:", is_active)
print("Is Verified:", is_verified)
print("User created successfully.")
if '__name__' == '__main__':
create_user("john", "password")
create_user("jane", "password123", is_admin=True)
create_user("alice", "pass123", is_active=False, is_verified=True)
2、可变参数
①可变参数args
需要添加 * ,用于接收任意数量的参数
def sum(*args):# 形参能够接收任意个长度的数据
pass
# 调用可变参数的函数
sum(10,20,30)
sum(10,20,30,40)
"""
可变参数的本质:传递的参数包装成了元组,实现多个参数的sum函数
"""
def sum(name, *args):
# 形参能够接收任意个长度的数据 args为元组类型
# 有其他参数的时候,*args要放在最后
result = 0
for ele in args:
result += ele
return result
②可变参数kwargs
可以接收不存在的关键字参数,定义参数前添加两个 *
def func(**kwargs):# kwargs 接收不存在的关键字参数
pass
# 调用不存在的关键字参数函数
func(name = '张三', age = 30, score = 70)
# 不存在的关键字参数包装成字典
def func(a,**kwargs):# kwargs 接收不存在的关键字参数 kwargs为字典类型
name = kwargs['name']
age = kwargs['age']
# 调用不存在的关键字参数函数
func(name = '张三',age = 30,a=10,score=70)
③传递元组/列表给可变参数args
def func(*args):
print(args)#(10,20,30)
t = (10,20,30)
# 传递元组,需要在元组/列表前加上*进行解包操作
func(*t)
④传递字典给可变参数kwargs
def func(**kwargs):
print(kwargs)
d = {'name':'张三', 'age':40}
# 传递字典给可变参数kwargs,在字典的前面加上**的作用是将字典中的元素解包成一个一个的不存在的关键字参数传递给函数
func(**d)
⑤组合使用
如何区分参数、*args和**kwargs?
-
参数(
kind
):-
它是函数定义中明确声明的普通位置参数。
-
在函数调用时,必须传递一个值给它,否则会报错。
-
它的位置是固定的,必须按照函数定义的顺序传递值。
-
-
位置参数(
*args
):-
它们是按顺序传递的,没有指定参数名。
-
在函数调用中,直接写在函数名后面的值(没有
key=
的形式)。 -
在函数内部,
*args
是一个元组,可以通过索引访问。
-
-
关键字参数(
**kwargs
):-
它们是以
key=value
的形式传递的。 -
在函数调用中,以
key=value
的形式指定的参数。 -
在函数内部,
**kwargs
是一个字典,可以通过键访问对应的值。
-
def milk_tea_shop(kind, *arguments, **keywords):
print("-- 老板,给我来杯", kind, "!")
print("-- 对不起,我们的 %s 已经卖完啦!" % kind)
for arg in arguments:
print(arg)
print("-" * 40)
for kw in keywords:
print(kw, ":", keywords[kw])
if '__name__' == '__main__':
milk_tea_shop(
"霸王茶几",
"半糖", "少冰", "加波霸", "加茶冻",
price="25元", address="太阳小区希望栋5114房",
phone="000-12345678"
)
3、递归函数
递归含义:
把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解,一个函数在内部调用其本身,这个函数就是 递归函数
递归的好处:
只需少量的程序就可描述出解题过程所需要的多次重复计算
def func(n):
'''
求n的阶乘
:param n: 需要求的阶乘
:return: n的阶乘
'''
if n==1:
return 1
else:
return n*func(n-1)
"""
斐波那契数列
"""
def fibonacci(n):
if n == 0:
return 0
elif n == 1:
return 1
else:
return fibonacci(n-1) + fibonacci(n-2)
4、文件I/O
①打开文件
f = open(文件名,访问模式)
文件名:文件的相对路径或者绝对路径
访问方式:文件的访问方式有读、写、追加
# 如果没有传入默认访问模式为r(只读)
f = open('a.txt')
访问模式:
r | r+ | w | w+ | a | a+ | |
读 | √ | √ | √ | √ | ||
写 | √ | √ | √ | √ | √ | |
创建 | √ | √ | √ | √ | ||
覆盖 | √ | √ | ||||
指针在开始 | √ | √ | √ | √ | ||
指针在结尾 | √ | √ |
②关闭文件
要保证文件操作完后要关掉,因为程序能打开的文件数量是有上限的,并且不关闭文件会造成内存泄漏
f.close()
③文件读取
1.read
f = open('a.txt', "r")
data = f.read(num) # 参数num: 默认-1,读取整个文件内容。可以指定num,读取num个数据
f.close()
# 读取5个数据
result = f.read(5)
# 读取整个文件内容
result = f.read()
2.readline
读取整个文件,返回每一行数据的列表
result = f.readlines()
with open('example.txt', 'r') as file:
line1 = file.readline()
line2 = file.readline()
print(line1, end='') # 打印第一行
print(line2, end='') # 打印第二行
# 逐行读取
with open('example.txt', 'r') as file:
for line in file:
print(line, end='') # 打印每一行
-
read()
:适合读取整个文件内容,尤其是当文件较小时。它会将整个文件内容加载到内存中,因此不适合处理大文件。 -
readline()
:适合逐行读取文件内容,尤其是当文件较大时。它每次只读取一行,内存占用较小,适合逐行处理文件。
④文件写入
1、write
f = open('test.txt','w')
f.write('hello world')
f.close()
2、writeline
lst = ['bill','gates','tom']
f = open('test.txt','w')
# 将列表中数据写入到文件中
f.writelines(lst)
f.close()
-
write()
:-
用于写入单个字符串。
-
如果需要写入多行,需要手动在每个字符串末尾添加换行符
\n
。 -
适合逐行写入时手动控制换行。
-
-
writelines()
:-
用于批量写入多个字符串。
-
不会自动添加换行符,需要在每个字符串中手动添加换行符
\n
。 -
适合一次性写入多行内容。
-
⑤with使用
处理文件对象时,最好使用 with
关键字。优点是,子句体结束后,文件会正确关闭,即便触发异常也可以。
# 读文件
with open('workfile.txt', encoding="utf-8") as f:
read_data = f.read()
with open('test.txt','w') as f:
f.write('hello world')
print(f.closed) # True
⑥绝对路径与相对路径
- 绝对路径指的是在电脑硬盘上真正保存的路径
- 相对路径就是相对于当前目录的路径
5、文件备份
# 1.输入文件名 b.txt
inputName = input('请输入文件名')
# 2.创建文件 文件名[复制].py
# inputName.find(),查找.所在的inedx
# inputName.rfind(),利用切片作字符串拼接
index = inputName.rfind('.')
copyName = inputName[:index] + '[复制]' +inputName[index:]
# 3.读取文件,写入到复制的文件中
# 打开源文件
inputFile = open(inputName)
# 打开复制的文件
copyFile = open(copyName,'w')
"""------------------ 读取一部分写入 ------------------"""
line = inputFile.readline()
while line:
# 有数据,写入文件
copyFile.write(line)
# 读取一行
line = inputFile.readline()
# 关闭文件
inputFile.close()
copyFile.close()