之前我们写的代码,都一行一行写,执行的时候,会把文件中所有的代码都会执行。代码不能复用。使用函数可以将公共使用代码封装起来,使用的时候,通过调用函数来实现代码的复用,减轻我们的维护成本。
定义函数
基本语法
通过关键字 def 进行定义函数。 def 后跟函数名,函数名的命名有如下规范:
- 函数名中除了
_
不能有其他特殊字符。 - 函数名中可以有数字,但是数字不能放在首位。一般都是放在后面。
- 函数名可以使用英文,但是不建议使用中文。一般命名都会使用有意义的名字。
# 定义最基本的函数
def f1():
pass
- f1 为函数名
- () 每个函数后面都需要有(), 固定的。
pass
表示函数的占位符,这个函数还没有实现逻辑,先占个位置。
在搭建框架的时候,可以先把主要函数定义出来,等后续实现,使用 pass 作为占位符。
下面来定义一个 写入文件的函数。
定义函数
def write_file():
with open('hello.txt',mode='w',encoding='utf8') as file:
# 写入文件, whitelines 需要 列表类型的数据
file.writelines(["hello","world"])
将执行的代码放在 函数内部。
函数定义好之后,只是定义好了而已,运行的时候不会执行。只用在调用的时候才能执行。
def write_file():
with open('hello.txt',mode='w',encoding='utf8') as file:
# 写入文件, whitelines 需要 列表类型的数据
file.writelines(["hello","world"])
#调用函数
write_file()
调用函数之后,运行代码就可以看到效果。
函数的参数
上面的函数定义的时候每次写入文件都是写入到 hello.txt 中,不够灵活,我们希望能够写入到不同的文件中。可以在定义函数的时候设置一个参数。
指定参数
def write_file_name(name):
"""
函数注释: 写入文件的时候提供一个文件名,指定写入的文件
:param name: 要写入的文件名
:return:
"""
with open(name,mode='w',encoding='utf8') as file:
file.write("helloworld")
# 调用函数的时候 需给函数传入一个具体值
write_file_name('fanmao.txt')
write_file_name('abc.txt')
- write_file_name 函数名
- (name) 函数的参数, name 表示传入的文件名, name 这里类似变量名,可以任意命名,比如也可以改为 filename 等, 需要注意,函数内部使用的时候,要跟(参数名) 要保持一致。
调用函数,传入对应的参数值。运行,可以看到执行结果。
函数也可以设置多个参数。
def write_file_filename_content(filename,filecontent):
"""
自定义内容写入指定文件
:param filename: 文件名字
:param filecontent: 文件中的内容
:return:
"""
with open(filename,mode='w',encoding='utf8') as file:
file.write(filecontent)
write_file_filename_content('china.txt','hahahahaha')
根据函数的功能,可以设置多个参数。
- 函数的注释, 可以让别人快速的了解这个函数是做什么的。这个注释可以加,也可以不加,规范的做法需要添加注释。
添加注释的好处就是再调用函数的时候,可以快速知道这个函数的功能。
鼠标移动到函数上可以看到注释。
函数参数的默认值
在定义函数的时候,可以为参数指定默认值。
# 定义函数的时候 使用默认值
def write_file_with_default_contet(filename,filecontent="helloworld"):
"""
定义函数 带有默认值参数
:param filename: 文件名
:param filecontent: 文件内容
:return:
"""
with open(filename,mode='w',encoding='utf8') as file:
file.write(filecontent)
# 函数定义的时候 有默认值, 调用的是不传参,运行的时候会自动使用默认值。
write_file_with_default_contet('b.txt') # 使用默认值
write_file_with_default_contet('c.txt',"hahaha") # 不使用默认值
调用的时候,如果有默认值的参数不传值,运行的时候会使用默认值。
传值就会覆盖默认值。
默认值的注意事项:
如果一个函数中有默认值,定义函数的时候,默认值的位置要放在后面,必填值的位置放在前面。上面定义的函数,定义的时候,参数的位置必须是这样 (filename,filecontent="helloworld")
不能将有默认值的参数放在前面 (filecontent="helloworld",filename)
这是错误的。
如果定义的函数 只有一个参数,参数也有默认值,直接定义即可。
def f1(name="xiaoming"):
print(f"hi,{name}")
#调用函数
f1() # 使用默认值
f1("小王")
函数的返回值
在定义的函数中 可以通过return 关键字来设置函数的返回值。比如函数中没有return ,这个函数的值默认为 None。
比如下面这个函数
def f1():
a = 1
b = 2
c = a+b
print(f1())
return 返回值
在函数内部通过使用 return 来返回结果。函数就有值了。
def f1():
a = 1
b = 2
c = a+b
return c
print(f1())
这个函数有 return 关键字,将c的结果return出来, 当调用f1() 函数的时候,就会返回对应的值。 c结果就可以给到f1()。
所以执行结果为 3
在做一些项目的时候,项目文件中有很多函数,这些函数之间是可以相互来使用的。 举个例子,在做电商的接口测试过程中。可以将每个接口的操作定义为函数。
def login():
"""
登录成功之后会返回token值
:return:
"""
token = "xxxxxx"
return token
def add_cart():
# 调用login() 函数
t = login() # login() 有返回值,login() 等价于 "abcdedf"
print(f'这里需要使用到login登录接口中的token值,{t}')
add_cart()
执行代码,可以看到 在add_cart() 函数通过调用 login() 函数,就能获取到 login() 函数中的返回值。就可以使用了。
是否使用return返回值
我们一般在编码的过程中,如果其他函数中有可能用到这个函数的运算结果,那么在定义的时候必须添加返回值。在其他函数中通过调用 来获取函数的返回结果。
加强练习
s1 = add_n(10) s2 = add_n(20) print(“计算1-10之和”,s1) print(‘计算1-20之和’,s2)
在编写程序的时候,也需要考虑异常场景。对上面的程序添加如下需求: 当传入参数值小于1的时候,返回None。
```python
# 计算1--n 之和 (n>=1) 如果传入值 n<1 打印 输入参数必须大于0 ,返回None
def add_n(n):
if n< 1:
print('输入参数必须大于0')
return None
else:
return sum(list(range(1,n+1)))
s1 = add_n(10)
s2 = add_n(20)
print("计算1-10之和",s1)
print('计算1-20之和',s2)
s3 = add_n(-10) # 异常场景
print(s3)
- 在做接口测试时候,用户注册接口,每次注册的时候都需要一个手机号码。这个手机号码不能重复的。为了做这个接口,我们可以通过定义一个函数生成一个随机的手机号,这样每次测试注册接口的时候,通过调用这个函数来生成随机手机号码进行注册。
# 导入python中的随机数生成模块
import random
def get_phone():
"""
生成一个随机的11手机号码, 手机号码中 前2位 ['13','14','15','17','18']
:return:
"""
# 定义一个空的字符串 表示手机号
phone=""
# 定义手机号的支持的前两位
pre_phone = ['13','14','15','17','18']
# 随机从列表中选择一个 需要使用到随机函数
p1 = random.choice(pre_phone) # 从列表中随机选择一个元素
print(p1)
# 将随机获取的前两位放到手机号中
phone=phone+p1
# 生成9位随机的数字 (0,9) 循环9次
for i in range(9):
# 生成1位随机数
n = random.randint(0,9)
print(n)
# 将随机数字添加到手机号 n 位数字,数字不能直接跟字符串拼接 str(n) 将数字转换位字符串
phone = phone+str(n)
# 循环完成之后将电话号码返回
return phone
p = get_phone()
print(f"生成随机电话 {p}")
- 将下面的代码使用 函数的方式进行封装。
对应的data.csv文件如下
data.csv
# 导入csv 进行 读取数据
import csv
# 打开csv 文件
with open('data.csv',mode='r',encoding='utf8') as f:
# 使用csv模块提供的方法创建一个对象
lines = csv.reader(f)
# 定义一个计数的变量
count=0
for line in lines:
# 打印出文件中的每一行内容
print(line)
#循环一次 count值增加1
count=count+1
# 前50行数据
if count<=50:
# 将内容写入到 txt 文件中
with open('a.txt',mode='a',encoding='utf8') as fa:
# whitelines 写入行内容,传入的数据需要列表类型
fa.writelines(line)
# 默认没有换行 换行
fa.write('\n')
else:
#后50行内容
with open('b.txt',mode='a',encoding='utf8') as fa:
fa.writelines(line)
# 换行
fa.write('\n')
分析上面的代码
写入文件有共同的部分,需要进行函数封装。
读取csv文件也可以进行封装, 现在暂时先定义两个函数。
import csv
# 文件写入, 需要提供写入的文件名,以及对应的文件内容。
def write_txt(filename,filecontent):
"""
写入文件
:param filename: 文件名
:param filecontent: 文件的内容
:return:
"""
with open(filename,mode='a',encoding='utf8') as f:
f.writelines(filecontent)
f.write('\n')
# 读取文件进行封装
def read_csv_file(csvfile):
# 定义空的列表,主要存放csv文件中的数据
csv_data = []
with open(csvfile,mode='r',encoding='utf8') as file:
lines = csv.reader(file)
# 使用csv 创建reader对象
for line in lines:
# 将每一次读取到的数据存放到 csv_data
csv_data.append(line)
#等文件中所有内容都读完,csv_data会保存所有的数据内容,将所有的数据返回
return csv_data
data = read_csv_file('data.csv')
print("csv文件中的所有的数据",data)
下面演示一下如何使用这些定义好的函数。
import csv
# 文件写入, 需要提供写入的文件名,以及对应的文件内容。
def write_txt(filename,filecontent):
"""
写入文件
:param filename: 文件名
:param filecontent: 文件的内容
:return:
"""
with open(filename,mode='a',encoding='utf8') as f:
f.writelines(filecontent)
f.write('\n')
# 读取文件进行封装
def read_csv_file(csvfile):
"""
读取csv文件的内容
:param csvfile: csv文件的路径
:return:
"""
# 定义空的列表,主要存放csv文件中的数据
csv_data = []
with open(csvfile,mode='r',encoding='utf8') as file:
lines = csv.reader(file)
# 使用csv 创建reader对象
for line in lines:
# 将每一次读取到的数据存放到 csv_data
csv_data.append(line)
#等文件中所有内容都读完,csv_data会保存所有的数据内容,将所有的数据返回
return csv_data
def run():
# 1. 先读取文件内容 data.csv 文件中的内容
# read_csv_file(r'C:\Users\zengy\PycharmProjects\pythonProject8\data.csv')
data = read_csv_file('data.csv')
# print(data)
# 2. 前50行数据写入到 a.txt 文件中
for i in range(50):
print(f'现在写入数据:{data[i]}')
write_txt('a.txt',data[i])
# 传入51-100内容到 b文件
for i in range(50,100):
write_txt('b.txt',data[i])
run()
作业
- 使用python生成随机身份证号(1960-2022出生)。
生成身份证号:
前6位 ** 地区
中间8位 yyyymmdd 年月日
最后4位 随机3位+随机1-9或者X
根据上面的分析
前6位 定义一个函数, 返回随机的地区
中间8位 定义函数, 返回 年月日
最后4位 定义函数
将上面3个函数返回结果拼接在一起,形成一个身份证号
使用到csv文件
gb2260.csv 存放所有的地区码
import csv
import random
def get_area():
"""
生成随机的6位地区信息
:return: 6个数字字符串
"""
# 从csv文件中读取所有的地区码,随机选择一个
# 定义空的list 用来存放地区码
area_code=[]
with open('gb2260.csv',mode='r',encoding='utf8') as file:
lines = csv.reader(file)
for line in lines:
# 每个地区码 都放在list 中
area_code.append(line)
# 随机从 所有地区码中选择一个
code = random.choice(area_code)
# code 值选择出来是 一个list 需要将list 转换位字符串
code_str = ''.join(code) # ''.join(code) 将list 转换位字符串
# 将随机选择的code 返回
return code_str
def get_birth():
"""
生成随机的 出生年月日 1960-2022出生
:return:
"""
def get_last():
"""
最后4位
:return:
"""
code = get_area()
print(f'code值 {code}')
主要点:
- 列表转换为字符串
names = ['helloworld'] # 转为字符串 n_str = "".join(names) print(n_str,type(n_str))
参考答案
import csv
import random
def get_area():
"""
生成随机的6位地区信息
:return: 6个数字字符串
"""
# 从csv文件中读取所有的地区码,随机选择一个
# 定义空的list 用来存放地区码
area_code=[]
with open('gb2260.csv',mode='r',encoding='utf8') as file:
lines = csv.reader(file)
for line in lines:
# 每个地区码 都放在list 中
area_code.append(line)
# 随机从 所有地区码中选择一个
code = random.choice(area_code)
# code 值选择出来是 一个list 需要将list 转换位字符串
code_str = ''.join(code) # ''.join(code) 将list 转换位字符串
# 将随机选择的code 返回
return code_str
def get_birth():
"""
生成随机的 出生年月日 1960-2022出生
:return:
"""
# 年份
year = random.randint(1960,2022)
# 月份
month = random.randint(1,12)
# 日
# 考虑闰年,月份
# 如果年份是闰年,并且月份2月, 有29天
if year%4 == 0 and month == 2:
day = random.randint(1,29)
# 在 1,3,5,7,8,10,12 月中 有31天
elif month in [1,3,5,7,8,10,12]:
day = random.randint(1,31)
elif month in [4,6,9,11]:
day = random.randint(1,30)
# 如果以上都不是 就是 平年的2月份
else:
day = random.randint(1,28)
# 如果天为个位数 前面添加0
if day<10:
day = "0"+str(day)
# 月份前 01, 02
if month < 10:
month = "0" + str(month)
# 返回年月日
return f'{year}{month}{day}'
def get_last():
"""
最后4位
:return:
"""
pre_3=""
for i in range(3):
n = random.randint(0,9)
pre_3 = pre_3+str(n)
last = random.choice(['0','1','2','3','4','5','6','7','8','9','X'])
# 返回
return f'{pre_3}{last}'
code = get_area()
dt = get_birth()
lt = get_last()
id = code+dt+lt
print('生成对应的身份证号',id)