本文最后更新于506 天前,其中的信息可能已经过时,如有错误请发送邮件到gedaling@foxmail.com
函数:内置函数、自定义函数
模块:内置模块、自定义模块、第三方模块
1、初识函数
函数,可以当做是一大堆功能代码的集合
def 函数名():
函数内便编写代码
...
...
函数名()
例如:
# 定义名字叫info的函数
def info():
print('第一行')
print('第二行')
print('第三行')
# 执行函数
info()
什么时候会用到函数?一般在项目开发中会有两种应用场景:
- 有重复代码
def send_email():
# 假设有10行代码
print('欢迎使用计算机监控系统')
if CPU使用率 > 90%:
send_email()
if 硬盘使用率 > 95%:
send_email()
if 内存使用率 > 99%:
send_email()
....
- 代码太长
def calculate_same_num_rule():
---判断是否是豹子---
pass
def calculate_same_color_rule():
---判断是否是同花---
pass
def calculate_straight_rule():
---判断是否是顺子---
pass
def calculate_double_card_rule(poke_list):
---判断是否是对子---
pass
def calculate_single_card_rule():
---判断是否是单牌---
pass
# 1.生成一副扑克牌
card_color_list = ['红桃', '黑桃', '方片', '梅花']
card_num = [1,2,3,4,5,6,7,8,9,10,11,12,13,14] # A
all_card_list = [(color,num) for color in card_color_list for num in card_mun]
# 2.洗牌
random.shuffle(all_card_list)
# 3.给玩家发牌
...
# 4.判断牌是:豹子?同花顺?顺子?对子?单点?
calculate_same_num_rule()
calculate_same_color_rule()
calculate_straight_rule()
...
以前是按照业务逻辑从上到下逐步完成,称为:面向过程编辑。
学习函数之后,利用函数编程,称为:函数式编程。
2、函数的参数
用python发邮件,由此引出函数的参数
- 注册邮箱,网易邮箱gedaling1995@163.com
- 基础配置
- 授权码:
- SMTP服务器地址:smtp.163.com
- 代码发送邮件:实例函数
import smtplib
from email.mime.text import MIMEText
from email.utils import formataddr
def send_email():
# 1.邮件内容配置
# 邮件文本
msg = MIMEText('约吗', 'html', 'utf-8')
# 邮件上显示发件人
msg['From'] = formataddr(['葛大令', 'gedaling1995@163.com'])
# 邮件上显示的主题
msg['Subject'] = '邮件主题'
# 2.发送邮件
server = smtplib.SMTP_SSL('smtp.163.com')
server.login('gedaling1995@163.com', 'SHEZLWSRSPANOYRJ')
server.sendmail('gedaling1995@163.com', '收件人邮箱', msg.as_string())
server.quit()
send_email()
问题:根据上述代码实现给三个用户发邮件。
# gedaling@qq.com
# 835848380@qq.com
# gedaling@foxmail.com
import smtplib
from email.mime.text import MIMEText
from email.utils import formataddr
def send_email(XX): # 函数添加参数(括号内)XX
# 1.邮件内容配置
# 邮件文本
msg = MIMEText('约吗', 'html', 'utf-8')
# 邮件上显示发件人
msg['From'] = formataddr(['葛大令', 'gedaling1995@163.com'])
# 邮件上显示的主题
msg['Subject'] = '180一晚'
# 2.发送邮件
server = smtplib.SMTP_SSL('smtp.163.com')
server.login('gedaling1995@163.com', 'SHEZLWSRSPANOYRJ')
server.sendmail('gedaling1995@163.com', XX, msg.as_string())
server.quit()
send_email('gedaling@qq.com')
send_email('835848380@qq.com')
send_email('gedaling@foxmail.com')
2.1、参数
在定义函数时,如果在括号中添加变量,称为函数的形式参数:
# 定义有三个参数的函数(a1/a2/a3一般称为形式参数-形参)
def func(a1, a2, a3):
print(a1 + a2 + a3)
# 执行函数并传入参数(执行函数传值时一般称为实际参数-实参)
func(11, 22, 33)
# 执行函数并传入参数
func(9, 2, 103)
func(a1=99, a2=88, a3=1) # 关键字传参
func(a3=1, a1=99, a2=88) # 关键字传参,位置可随意
# 执行函数(位置传参在前,关键字传参在后)
func(99, a2=88, a3=1) # 混合传参
func(99, 88, a3=1) # 混合传参
func(a1=99, 88, a3=1) # ✖错误,不允许
- 位置传参
def add(n1, n2):
print(n1 + n2)
add(1, 22)
- 关键字传参
def add(n1, n2):
print(n1 + n2)
add(n1=1, n2=22)
2.2、默认参数
# 定义有三个参数的函数
def func(a1, a2, a3=10): # 定义了一个默认值
print(a1 + a2 + a3)
# 位置传参
func(8, 19)
func(1, 2, 99) # 99会覆盖默认值a3=10
# 关键字传参(位置传参在前,关键字传参在后)
func(12, 9, a3=90) # 混合传参
func(12, a2=9, a3=90) # 混合传参
func(a1=12, a2=9, a3=90) # 关键字传参
2.3、动态参数
- ※
def func(*args): # 定义了一个动态参数/变量 print(args) # 元组类型 args[0] # 元组索引 # 只能按位置传参 func() # 空元组 () func(22) # (22) func(22, 33) # (22,33) func(22, 33, 99) # (22,33,99)
- ※※
def func(**kwargs): # 定义了一个动态参数/变量 print(kwargs) # 字典类型 # 只能按关键字传参 func() # 空字典 func(n1='武沛齐') # {'n1':'武沛齐'} func(n1='武沛齐', age=18) # {'n1':'武沛齐', 'age':'18'} func(n1='武沛齐', age=18, email='xx@qq.com')
- ※,※※
def func(*args,**kwargs): # 定义了二个动态参数/变量 print(args,kwargs) # 可以按关键字和位置混合传参,并能自动识别参数类型为args/kwargs func() # () {} func(22, 33, 99) # (22,33,99) {} func(n1='武沛齐', age=18) # () {'n1':'武沛齐', 'age':'18'} func(22, 33, 99, n1='武沛齐', age=18) # (22,33,99) {'n1':'武沛齐', 'age':'18'}
提示:对比之前所学字符串格式化时的format功能
v1 = '我叫{}, 今年{}, 性别{}'.format('武沛齐', 18, '男') # 位置传参
v2 = '我叫{name}, 今年{age}, 性别{gender}'.format(name='武沛齐', age=18, gender='男') # 关键字传参
- 注意事项
# 1、**kwargs必须放在*args后面 def func1(*args, **kwargs): print(args, kwargs) # 2、参数和动态参数混合时,动态参数只能放在后面 def func2(a1, a2, a3, *args, **kwargs): print(a1, a2, a3, args, kwargs) # 3、默认值参数和动态参数同时存在,默认值要放在**kwargs前 def func3(a1, a2, a3, a4=10, *args, a5=20, **kwargs): print(a1, a2, a3, a4, a5, args, kwargs)
3、函数返回值
在开发过程中,我们希望函数可以帮助我们实现某个功能,但让函数实现某功能之后有时也需要有一些结果需要反馈给我们,例如:
import requests
from xml.etree import ElementTree as ET
def xml_to_list(city):
data_list = []
url = 'http://ws.webxml.com.cn//WebServices/WeatherWebService.asmx/getWeatherbyCityName?theCityName={}'.format(city)
res = requests.get(url=url)
root = ET.XML(res.text)
for node in root:
data_list.append(node.text)
return data_list
result = xml_to_list('北京')
print(result) # ['直辖市', '北京', '54511', '54511.jpg', '2023/12/13 16:44:19', '-5℃/-2℃', '12月13日 中雪转小雪', '东风小于3级', '15.gif', '14.gif', '今日天气实况:气温:-2.1℃;风向/风力:东风 2级;湿度:88%;紫外线强度:最弱。', '感冒指数:极易发,寒冷潮湿,易发生感冒。\n运动指数:较不宜,有降水,推荐您在室内进行休闲运动。\n过敏指数:极不易发,无需担心过敏,可放心外出,享受生活。\n穿衣指数:寒冷,建议着厚羽绒服等隆冬服装。\n洗车指数:不宜,有雪,雪水和泥水会弄脏爱车。\n紫外线指数:最弱,辐射弱,涂擦SPF8-12防晒护肤品。\n', '-5℃/-2℃', '12月14日 中雪转小雪', '东北风小于3级', '15.gif', '14.gif', '-12℃/-2℃', '12月15日 多云', '西北风3-4级', '1.gif', '1.gif', '北京位于华北平原西北边缘,市中心位于北纬39度,东经116度,四周被河北省围着,东南和天津市相接。全市面积一万六千多平方公里,辖12区6县,人口1100余万。北京为暖温带半湿润大陆性季风气候,夏季炎热多雨,冬季寒冷干燥,春、秋短促,年平均气温10-12摄氏度。北京是世界历史文化名城和古都之一。早在七十万年前,北京周口店地区就出现了原始人群部落“北京人”。而北京建城也已有两千多年的历史,最初见于记载的名字为“蓟”。公元前1045年北京成为蓟、燕等诸侯国的都城;公元前221年秦始皇统一中国以来,北京一直是中国北方重镇和地方中心;自公元938年以来,北京又先后成为辽陪都、金上都、元大都、明清国都。1949年10月1日正式定为中华人民共和国首都。北京具有丰富的旅游资源,对外开放的旅游景点达200多处,有世界上最大的皇宫紫禁城、祭天神庙天坛、皇家花园北海、皇家园林颐和园,还有八达岭、慕田峪、司马台长城以及世界上最大的四合院恭王府等各胜古迹。全市共有文物古迹7309项,其中国家文物保护单位42个,市级文物保护单位222个。北京的市树为国槐和侧柏,市花为月季和菊花。另外,北京出产的象牙雕刻、玉器雕刻、景泰蓝、地毯等传统手工艺品驰誉世界。']
def func():
return 666
res = func()
print(res) # 666
def magic(num):
result = num + 1000
return result
data = magic(9)
print(data) # 1009
- 返回值可以是任意类型,如果函数中没写return,则默认返回None
def func1(): return [1, True, (11, 22, 33)] result = func1() print(result) # [1, True, (11, 22, 33)] def func2(): value = 1 + 1 ret = func2() print(ret) # None
当在函数中未写返回值或return或return None,执行函数获取的返回值都是None
def func(): value = 1 + 1 return # 或 return None ret = func() print(ret) # None
- return后面的值如果有逗号,则默认会将返回值转换成元组再返回
def func(): return 1,2,3 ret = func() print(ret) # (1,2,3)
- 函数一旦遇到return就会立即退出函数(终止函数中的所有代码)
def func1(): print(1) return '结束吧' # 函数终止 print(2) ret = func1() print(ret) # 1 # 结束吧 def func2(): print(1) for i in range(10): print(i) return 999 # 函数终止 print(2) result = func2() print(result) # 1 # 0 # 999 def func3(): print(1) for i in range(10): print(i) for j in range(100): print(j) return # 函数终止 print(2) data = func3() print(data) # 1 # 0 # 0 # None
小结:
- 完成某个结果并希望得到结果
def send_email(): ... # 发邮件代码 return True v1 = send_mail() # 发送成功返回True def encrypt(old): ... # 给内容加密代码 return '密文...' data = encrypt('武沛齐') print(data)
- 基于return控制使函数终止执行
def foo(): while True: num = input('请输入数字(Q退出):') if num.upper() == 'Q': break # while循环终止,继续运行之后的代码 num = int(num) if num == 99: print('猜对了') else: print('猜错了,请继续!') print('666') foo() # 输入Q,输出666 def foo(): while True: num = input('请输入数字(Q退出):') if num.upper() == 'Q': return # 函数终止运行,跳出所有代码 num = int(num) if num == 99: print('猜对了') else: print('猜错了,请继续!') print('666') foo() # 输入Q,输出None
总结
1、如何定义一个函数?
2、函数名的规范(同变量名规范)
- 规范
- 建议
def change_num(): pass
3、函数的额注释,说明函数的作用
def encrypt(origin):
"""用于数据加密和XXX"""
pass
4、定义函数时,参数一般有以下情况(形式参数)
- 情景一
def func(a1,a2): pass
- 情景二
def func(a1,a2=123): pass
- 情景三
def func(*args,**kwargs): pass
5、函数的返回值,一般用于将行数执行的返回给调用者
- 默认返回None
- 遇到return则函数执行完毕
作业
1、请定义一个函数,用于计算一个字符串中字符a出现的次数并通过return返回
- 参数,字符串
- 返回值,字符串中a出现的次数
def char_count(text):
count = 0
for char in text:
if char == 'a':
count += 1
return count
result = char_count('89alssefea55aweraf565eaa')
print(result) # 6
2、写函数,判断用户传入的一个值(字符串或列表或元组任意)长度是否大于5,并返回真假
def judge_length(data):
if len(data) > 5:
return True
return False
result = judge_length('武沛齐武沛齐')
print(result) # True
3、写函数,接受两个数字参数,返回比较大的那个数字
def get_bigger(num1, num2):
if num1 > num2:
return num1
return num2
result = get_bigger(11, 22)
print(result)
4、写函数,函数接受四个参数分别是:姓名,性别,年龄,学历,然后将这四个值通过“**”拼接起来追加到一个student_msg.txt文件中
def write_file(name, gender, age, degree):
data_list = [name, gender, age, degree]
data = '*'.join(data_list)
with open('student_msg.txt', mode='a', encoding='utf-8') as file_object:
file_object.write(data)
write_file('武沛齐', '男', '18', '博士')
# 生成一个student_msg.txt文件,文本内容“武沛齐*男*18*博士”
5、补充代码,实现如下功能:
- 【位置1】读取文件中的每一行数据,将包含特定关键字的数据筛选出来,并以列表形式返回。
- 【位置1】文件不存在,则返回None
- 【位置2】文件不存在,输出“文件不存在”,否则循环输出匹配成功的每一行数据。
import os
def select_content(file_path, key):
# 补充代码【位置1】
if not os.path.exists(file_path):
return
data_list = []
with open(file_path, mode='r', encoding='utf-8') as file_object:
for line in file_object:
if key in line:
data_list.append(line)
return data_list
result = select_content('files/xxx.txt', '股票')
# 补充代码【位置2】
if result == None:
print('文件不存在')
else:
print(result)
6、补充代码,实现敏感词替换功能
def change_string(origin):
# 补充代码,将字符串origin中的敏感词替换为 ** ,最后将替换好的值返回
data_list = ['苍老师', '波多老师', '大桥']
for item in data_list:
origin = origin.replace(item, '*')
return origin
text = input('请输入内容:')
result = change_string(text)
print(result)
7、基于函数实现用户认证,要求:
- 写函数,读取的用户信息并构造为字典(用户信息放在files/user.xlsx文件中)
ID 用户名 密码 1 wupeiqi 21232f297a57a5a743894a0e4a801fc3 2 root 4297f44b13955235245b2497399d7a93 3 alex e10adc3949ba59abbe56e057f20f883e import hashlib from openpyxl import load_workbook def get_user_dict(): user_dict = {} wb = load_workbook('files/user.xlsx') sheet = wb.worksheets[0] for row in sheet.rows: user_dict[row[1].value] = row[2].value return user_dict def encrypt(origin): origin_bytes = origin.encode('utf-8') md5_object = hashlib.md5() md5_object.update(origin_bytes) return md5_object.hexdigest() user = input('请输入用户名:') pwd = input('请输入密码:') encrypt_password = encrypt(pwd) user_dict = get_user_dict() db_password = user_dict.get(user) if encrypt_password == db_password: print('登录成功') else: print('登录失败')
- 用户输入的用户名和密码,进行校验。(且密码都是密文,所以,需要将用户输入的密码进行加密,然后再与Excel中的密文密码进行比较)
import hashlib def encrypt(origin): origin_bytes = origin.encode('utf-8') md5_object = hashlib.md5() md5_object.update(origin_bytes) return md5_object.hexdigest() p1 = encrypt('admin') print(p1) # 21232f297a57a5a743894a0e4a801fc3 p2 = encrypt('123123') print(p2) # 4297f44b13955235245b2497399d7a93 p3 = encrypt('123456') print(p3) # e10adc3949ba59abbe56e057f20f883e
扩展:密码都是不是明文
- 注册京东,京东存储:用户名和密码(密文)
- 登录京东:用户名&密码。(转成密文对比存储中的密文数据)