文章目录
6.2 函数的定义与调用
6.2.1 定义函数
def 函数名(参数列表):
" 函数_文档字符串"
函数体
return 表达式
- 函数代码块以
def
开头,后面是函数名
和圆括号()
- 函数命名规则:只能是字母、数字、下划线的任意组合,但不能以数字开头,并且不能跟关键字重名
- 参数放在圆括号内
- 函数的第一行语句可以选择性的使用文档字符串来存放函数说明
- 函数内容以冒号开始,并且缩进
- return 表达式结束函数,选择性的返回一个值给调用方。不带表达式 return 相当于返回
None
# 定义一个函数
def print_init():
print("----------------------------------------")
print(" 人生苦短,我用Python ")
print("----------------------------------------")
6.2.2 调用函数
通过 “函数名()"
即可
print_init()
6.3 函数的参数
6.3.1 函数参数的传递
def add(a, b):
c = a + b
print(c)
add(11, 22)
6.3.2 默认参数
定义函数时,可以给函数的参数设置默认值。当调用时可以忽略默认参数,传入其他参数。如果默认参数没有传入,则调用默认参数;如果传入默认参数值,则用传入的新值代替。
def print_info(name, age=18):
print("Name: ", name,end=' ')
print("Age: ", age)
print_info(name='Ammy', age=29)
print_info('ann', 20)
带有默认值得参数放于最后,否则会报错。
6.3.3 不定长参数
通常在定义一个函数时,希望函数能够处理个数比当初定义的参数个数多,此时可以在函数中使用不定长参数。
def 函数名([formal_args,] *args, **kwargs):
"函数_文档字符串"
函数体
return 表达式
-
formal_args: 为形参(也就是前面所用的参数,如 a,b)
-
*args
和**kwargs
为不定长参数。当调用函数的时候,函数传入的参数个数会优先匹配
formal_args
参数的个数。如果传入的参数个数和formal_args
个数相等,不定长参数会返回空的元组或字典;如果传入的参数个数比formal_args
参数个数多,可以分一下两种情况:- 如果传入的参数没有指定名称,那么
*args
会以元组的形式存放这些多余的参数、 - 如果指定了名称,如
m = 1
,那么**kwargs
会以字典的形式存放这些被命名的参数。如:{m:1}
- 如果传入的参数没有指定名称,那么
def test (a, b, *args):
print(a)
print(b)
print(args)
test(11, 22)
当传入参数大于两个时
def test (a, b, *args, **kwargs):
print(a)
print(b)
print(args)
print(kwargs)
test(11, 22, 33, 44, 55, m = 66, n = 77)
6.4 函数的返回值
给调用者的结果。
def add(a+b):
return a + b
6.5 函数的四种类型
- 无参数,无返回值
- 无参数,有返回值
- 有参数,无返回值
- 有参数,有返回值
6.5.1 无参数,无返回值
def print_menu():
print('-'*20)
print(' xx点餐系统 ')
print(' 1. A')
print(' 2. B')
print('-'*20)
print_menu()
6.5.2 无参数,有返回值
def get_temoerature():
# 经过一些过程
# 获取温度结果
return 26
temperature = get_temoerature()
print(temperature)
6.5.3 有参数,无返回值
def test(num_one, num_two):
result = num_one + num_two
print(result)
6.5.4 有参数,有返回值
def calculate(number):
result = 0
i = 1
while(i <= number):
result += i
i += 1
return result
result = calculate(100)
print("1 ~ %d 的累加和为:%d"%(number, result))
6.6 函数案例——名片管理器
-
输出名片管理器的菜单
def display_menu(): print('-' * 30) print(' 名片管系统 v8.8') print('1. 添加名片') print('2. 删除名片') print('3. 修改名片') print('4. 查询名片') print('5. 获取所有名片信息') print('6. 推出系统') print('-'*30)
-
获取用户输入信息
def get_choice(): selected_key = input('请输入选择的序号:') return int(selected_key) # 等待用户选择 key = get_choice()
-
通过获取序号、执行不同的功能
# 菜单 def display_menu(): print('-' * 30) print(' 名片管系统 v8.8') print('1. 添加名片') print('2. 删除名片') print('3. 修改名片') print('4. 查询名片') print('5. 获取所有名片信息') print('6. 推出系统') print('-' * 30) name_list = [] i = 0 while i < 1: display_menu() # 获取用户输入信息 def get_choice(): selected_key = input('请输入选择的序号:') return int(selected_key) # 等待用户选择 key = get_choice() # 通过获取序号、执行不同的功能 # 1. 添加名片 def add_info(): new_name = input('请输入名字:') name_list.append(new_name) # 5. 获取所有名片信息 def print_all_info(temp_list): print('='*30) for info in temp_list: print(info) print('=' * 30) if key == 1: add_info() elif key == 2: pass elif key == 3: pass elif key == 4: pass elif key == 5: print_all_info(name_list) elif key == 6: pass else: print('输入内容有误,请重新输入...')
6.7 函数的嵌套调用
# 函数嵌套
def func_one():
print('---- func_one start ----')
print(' 代码 ')
print('---- func_one end ----')
def func_two():
print('---- func_two start ----')
func_one()
print('---- func_two end ----')
func_two()
6.8 变量作用域
6.8.1 LEGB原则
a = 10
def test():
a = 20
print(a)
test()
打印的 a 的值为 20,这是因为变量作用域不同所导致的。
python作用域:
1. L (Local): 哈描述内的区域,包括局部变量和参数。
2. E (Enclosing): 外面嵌套函数区域,常见的是闭包函数的外层函数。
3. G (Global): 全局作用域。
4. B (Built_in): 内建作用域。
Python中采取 L->E->G->B
的规则查找
6.8.2 全局变量和局部变量
局部变量指定义在函数内的变量。只能在 def
函数内使用,他与函数外具有相同名称的其他变量没有任何关系,不同的函数可以定义相同名字的局部变量,并且各个函数内的变量不会产生影响。
def test_one():
number = 100
print('tese_one 中的 number 值为:%d'%number)
def test_two():
number = 200
print('tese_two 中的 number 值为:%d' % number)
test_one()
test_two()
局部变量只能在其被声明的函数内部访问,全局可以在整个程序范围内访问。
result = 100
def sum(a,b):
result = a + b
print('函数内部的 result 值:', result)
return result
sum(100,200)
print('函数外部的 result 值:', result)
6.8.3 global 和 nonlocal 关键字
当内部作用域想修改外部作用域的变量时,就要用到 global
和 nonlocal
关键字。
-
global 关键字
global 关键字用来在函数或者其他局部作用域中使用全局变量。但是如果不修改全局变量也可不使用 global
>>> a = 100 >>> def test(): ··· a += 100 ··· print(a) ··· >>> test() 200
-
nonlocal
可以在一个嵌套的函数中修改嵌套作用域中的变量。
-
没有使用 nonlocal
>>> def func(): ··· count = 1 ··· def func_in(): ··· count = 12 ··· func_in() ··· print (count) ··· >>> func() 1
-
使用 nonlocal
>>> def func(): ··· count = 1 ··· def func_in(): ··· nonlocal count ··· count = 12 ··· func_in() ··· print (count) ··· >>> func() 12
-
global 修饰的变量之前可以不存在,nonlocal 修饰的变量在嵌套作用域中必须已存在。
6.9 递归函数和匿名函数
6.9.1 递归函数
如果在一个函数的内部调用了函数本身,那么这个函数就是递归函数。
def func(num):
if num == 1:
return 1
else:
return func(num - 1) * num
# return result
number = int(input("输入数字 number:"))
print(func(number))
6.9.2 匿名函数
声明匿名函数使用 lambda
关键字。
lambda [arg1[, arg2,...argn]]: experssion
[arg1[, arg2,...argn]]
表示函数的参数,experssion
函数的表达式。
add = lambda a,b : a+b
print(add(10,20))
print(add(20,20))
使用 lambda
声明的匿名函数能够接收任何数量的参数,但是能返回一个表达式的值。他不能直接调用 print()
函数,因为他需要一个表达式。
def func(a,b,operation):
print('a=%d'%a)
print('b=%d'%b)
print('result=',operation(a,b))
func(11,22,lambda x,y:x+y)
func(11,22,lambda x,y:x-y)
匿名函数可以作为内置函数的参数来使用。
students = [
{'name':'zhangsan','age':18},
{'name':'lisi','age':19},
{'name':'wangwu','age':17}
]
# 按 name 排序
students.sort(key = lambda x:x['name'])
print('按 name 排序后的结果:',students)
# 按 age 排序
students.sort(key = lambda x:x['age'])
print('按 age 排序后的结果:',students)
注意:
与 def
定义的函相比,lambda
定义的函数有很多不同的地方
1. `def` 定义的函数是有名称的,而 `lambda` 定义的函数没有函数名称
2. `lambda` 定义的函数通常会返回一个对象或者一个表达式,他不会将返回结果赋给一个变量,而 `def` 定义的函数则可以。
3. `lambda` 定义的函数只有一个表达式,而 `def` 定义的函数是一个语句。
4. `lambda` 表达式的冒号后面只能有一个表达式
5. 像 `if` 或 `for` 等语句不能用于 `lambda` 定义的函数中
6. `lambda` 一般用来定义简单的函数,而 `def` 定义复杂函数
7. `lambda` 定义的函数不能共享给别的程序调用
6.10 日期时间函数
time
和 calendar
模块用于格式化日期和时间。
6.10.1 时间函数
1. 时间戳
时间戳:从1970.01.01 00:00:00
开始按秒计算的偏移量。返回时间戳的函数主要有 time()、clock()
等
# 时间戳
import time
ticks = time.time()
print('当前时间戳:',ticks)
2. 格式化的时间字符串
使用 time
模块的 strftime
函数来格式化日期。
time.strftime(format[, t])
# 格式化时间字符串
import time
# print(time.localtime())
# 格式成 Y-m-d H:M:S
print('='*20)
print('格式成 Y-m-d H:M:S')
print(time.strftime("%y-%m-%d %H:%M:%S", time.localtime()))
# 格式成 周 月 日 时:分:秒 年 形式
print('+'*20)
print('格式成 周 月 日 时:分:秒 年 形式')
print(time.strftime('%a %b %d %H:%M:%S %Y', time.localtime()))
# 将格式字符串转换为时间戳
print('-'*20)
print('将格式字符串转换为时间戳')
time_word = time.strftime('%a %b %d %H:%M:%S %Y', time.localtime())
print(time.mktime(time.strptime(time_word,'%a %b %d %H:%M:%S %Y')))
test = time.strftime("%y-%m-%d %H:%M:%S", time.localtime())
print(time.mktime(time.strptime(test,"%y-%m-%d %H:%M:%S")))
print('-'*20)
格式化符号 | 含义 |
---|---|
%y | 两位数的年份表示(00~99) |
%Y | 四位数的年份表示(000~9999) |
%m | 月份(01~12) |
%d | 月内中的一天 |
%H | 24小时制小时数(0~23) |
%I | 12小时制小时数(0~12) |
%M | 分钟数(00~59) |
%S | 秒(00~59) |
%a | 本地简化的星期名称 |
%A | 本地完整星期名称 |
%b | 本地简化的月份名称 |
%B | 本地完整月份名称 |
%c | 本地响应的日期表示和时间表示 |
%j | 年内的一天(001~366) |
%p | 本地 A.M. 或 P.M. 等价符 |
%U | 一年中星期数(00~53),星期一为星期的开始 |
%w | 星期(0~6),星期天为星期的开始 |
%x | 本地相应的日期表示 |
%X | 本地相应的时间表示 |
%Z | 当前时区的名称 |
%% | %本身 |
3. 时间元组(struct_time)
返回 struct_time
的函数主要有 gmtime()
localtime()
strprime()
,struct_time 元组共有 九 个元素。
序号 | 字段 | 含义及取值范围 |
---|---|---|
0 | tm_year | 4 位数的年份,例如 2022 |
1 | tm_mon | 表示月份, 1~12 |
2 | tm_mday | 表示天数, 1~31 |
3 | tm_hour | 表示小时, 1~23 |
4 | tm_min | 表示分钟数, 0~59 |
5 | tm_sec | 表示秒数, 0~61(60或61是闰秒) |
6 | tm_wday | 表示星期数, 0~6(0是周一) |
7 | tm_yday | 表示一年中第几天, 1~366 |
8 | tm_isdst | 决定是否位夏令时的标识符,允许值为 -1, 0, 1 |
time
模块提供其他函数,如: sleep()
函数用于推迟调用线程的运行。
序号 | 代表含义 |
---|---|
1 | time.altzone 返回格林威治西部的夏令时地区的偏移秒数。如果该地区在格林威治东部会返回负值(如西欧)。对夏令时启用地区才能使用 |
2 | time.asctime([tupletime]) 接收时间元组并返回一个可读的形式为“Tue Dec 11 18:07:12 2022”的 24 个字符的字符串 |
3 | time.clock() 用以浮点数计算的秒数返回当前的 CPU 时间。用来衡量不同程序的耗时,比time.time()更有用 |
4 | time.ctime([secs]) 作用相当于 asctime(localtime(secs)).未提供参数相当于 asctime() |
5 | time.gmtime([secs]) 接收时间辍(1970年1月1日00:00:00后经过的浮点秒数)并返回格林威治天文时间下的时间元组 t。注:t.tm_isdst始终为0 |
6 | time.localtime([secs]) 接收时间缀(1970年1月1日00:00:00后经过的浮点秒数)并返回当地时间下的时间元组t(t.tm_isdst可取0或1,取决于当地当时是不是夏令时) |
7 | time.mktime(tupletime) 接收时间元组并返回时间辍(1970年1月1日00:00:00后经过的浮点秒数) |
8 | time.sleep(secs) 推迟调用线程的运行,Secs指秒数 |
9 | time.strftime(fmt[,tupletime]) 接收时间元组,并返回以可读字符串表示的当地时间,格式由 fmt 决定 |
10 | time.strptime(str,fmt=‘%a %b %d %H:%M:%S %Y’) 根据fmt的格式把一个时间字符串解析为时间元组 |
11 | time.time() 返回当前时间的时间戳(1970纪元后经过的浮点秒数) |
12 | time.tzset() 根据环境变量 TZ 重新初始化时间相关设置 |
除此之外,time还包括一下两个非常重要的属性
序号 | 属性说明 |
---|---|
1 | time.timezon 属性 time.timezon 是当地时区(未启动夏令时)距离格林威治的偏移秒数(>0,美洲;<= 0大部分欧洲,亚洲,非洲) |
2 | time.tzname 属性 time.tzname 包含一对根据情况的不同而不同的字符串,分别是带夏令时的本地时区名称和不带名称的 |
6.10.2 日历函数
calendar
模块提供中方法可以处理年历和月历。
print('-'*20)
import calendar
calendar_march = calendar.month(2022,7)
print('输出 2022 年 7 月日历')
print(calendar_march)
序号 | 函数和说明 |
---|---|
1 | calendar.calendar(year, w=2, l=1,c=6) 返回一个多行字符串格式的 year 年年历,三个月一行,间隔距离为 c。每日宽度间隔为 w 字符。每行长度为 21*w+18+2*c. l 是每星期行数。 |
2 | calendar.firstweekday() 返回当前每周其实日期的设置。默认情况下,首次载入 calendar 模块时返回 0,即星期一 |
3 | calendar.isleap(year) 是闰年返回 True, 否则返回 False |
4 | calendar.leapdays(y1,y2) 返回在 y1, y2 两年之间的闰年总数 |
5 | calendar.month(year,month,w=2,l=1) 返回一个多行字符串格式的 year 年 month 月日历,两行标题,一周一行。每日宽度间隔为 w 字符。每行的长度为 7*W+6。l是每星期的行数 |
6 | calendar.monthcalendar(year,month) 返回一个整数的单层嵌套列表。每个子列表装载代表一个星期的整数。year 年month 月外的日期都设为0;范围内的日子都由该月第几日表示,从1开始 |
7 | calendar.monthrange(year,month) 返回两个整数。第1个是该月的星期几的日期码,第2个是该月的日期码。日从0(星期一)6(星期日),月份为1(1月)12(12月) |
8 | calendar.prcal(year,w=2,I=1,c=6) 相当于print(calendar.calendar((year,w,l,c) |
9 | calendar.prmonth(year,month,w=2,l=1) 相当于print(calendar.calendar(year,w,I,c) |
10 | calendar.setfirstweekday(weekday) 设置每周的起始日期码。0(星期一)~6(星期日) |
11 | calendar.timegm(tupletime) 和time.gmtime相反:接收一个时间元组形式,返回该时刻的时间辍(1970纪元后经过的浮点秒数) |
12 | calendar.weekday(year,month,day) 返回给定日期的日期码。0(星期一)6(星期日)。月份为1(1月)12(12月) |
6.11 随机数函数
-
random.random()
返回 0 与 1 之间的随机浮点数 N。
import random print('random():',random.random()) print('random():',random.random())
-
random.uniform(a,b)
返回
[a,b]
的随机浮点数.import random print(random.uniform(20,12)) print(random.uniform(25,100))
-
random.randint(a,b)
返回
[a,b]
的随机整数。此时a <= bimport random print(random.randint(10,20)) print(random.randint(1,20))
-
random.randrange([start], stop[, setp])
返回指定递增基数集合中的一个随机数,基数默认值为 1。其中
start
参数用于指定范围内的开始值,其包含在内;end
参数用于指定范围内的结束值,其不包含在内;step
表示递增基数。import random print(random.randrange(10,100,2)) # 等价于从 [10, 12, 14, 16...98]中随机获取一个整数
-
random.choice(sequence)
从
sequence
中返回一个随机的元素。sequence
参数可以是列表、元组、字典或字符串。参数为空,报错import random a = random.choice("学习Python") b = random.choice(["JGood", 'is', 'a', 'handsome', 'boy']) c = random.choice(("Tuple", 'List', 'Dict')) print(a) print(b) print(c)
-
random.shuffle(x[, random])
用于将列表中的元素打乱顺序。
import random demo_list = ['Python', 'is', 'powerful', 'simple', 'and so on...'] random.shuffle(demo_list) print(demo_list)
-
random.sample(sequence, k)
从指定序列随机获取 k 个元素作为一个片段返回,
sample
函数不会修改原有序列。import random list_num = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] slice = random.sample(list_num,5) print(slice) print(list_num)
6.12 学生管理系统
学生管理系统负责编辑学生的信息。适时更新学生的资料。
- 使用自定义函数,完成对程序的模块化
- 学生信息至少包含:姓名、性别、手机号
- 该系统具有:添加、删除、修改、显示、退出系统
# 用来保存学生的所有信息
student_infos = []
# 打印功能提示
def print_menu():
print('='*30)
print(' 学生管理系统 ')
print('1. 添加学生信息')
print('2. 删除学生信息')
print('3. 修改学生信息')
print('4. 显示所有学生信息')
print('0. 退出系统')
print('='*30)
# 添加学生信息
def add_info():
# 提示并获取学生的姓名
new_name = input('输入学生姓名:')
# 提示并获取学生的性别
new_sex = input('输入学生性别:(男 / 女)')
# 提示并获取学生的手机号
new_phone = input('输入学生手机号:')
new_infos = {}
new_infos['name'] = new_name
new_infos['sex'] = new_sex
new_infos['phone'] = new_phone
student_infos.append(new_infos)
# 删除学生信息
def del_info(student):
del_number = int(input('输入要删除的编号:')) - 1
del student[del_number]
# 修改学生信息
def modify_info():
student_id = int(input('要修改的学生序号:'))
new_name = input('输入学生姓名:')
new_sex = input('输入学生性别:(男 / 女)')
new_phone = input('输入学生手机号:')
student_infos[student_id - 1]['name'] = new_name
student_infos[student_id - 1]['sex'] = new_sex
student_infos[student_id - 1]['phone'] = new_phone
# 显示所有学生信息
def show_info():
print('='*30)
print('学生信息如下:')
print('='*30)
print('序号 姓名 性别 手机号码')
i = 1
for tmp in student_infos:
print('%d %s %s %s'%(i, tmp['name'], tmp['sex'], tmp['phone']))
i += 1
# 定义主函数
def main():
while True:
print_menu() # 打印菜单
key = int(input('输入功能序号:')) # 获取用户输入的序号)
if key == 1: # 添加学生信息
add_info()
elif key == 2: # 删除学生信息
del_info(student_infos)
elif key == 3: # 修改学生信息
modify_info()
elif key == 4: # 显示所有学生信息
show_info()
elif key == 0: # 退出系统
quit_confirm = input('确认退出?(Yes or No):')
if quit_confirm == 'Yes':
break
else:
print('输入信息有误,请重新输入。')
main()