
一、函数的定义二、4种函数的参数形式三、函数返回值四、函数的作用域,全局/局部变量五、函数的嵌套六、函数的递归七、匿名函数lambda八、匿名函数lambda的应用九、匿名函数和常规函数对比十、函数式编程的特点十一、函数式编程map()、filter()、reduce()函数十二、函数式编程map() VS 列表推导式十二、函数是一等公民十三、函数装饰器十三、带参数的函数装饰器十三、不定长参数的函数装饰器十四、防止被装饰的函数改变十五、函数装饰器的嵌套银行系统综合案例prettytable将二维数组的打印美化成表格
一、函数的定义# 创建高楼
def create_building():
# 创建房间
create_room()
# 创建电梯
create_stair()
def create_room():
print('开始创建房间')
print('正在创建房间')
print('创建房间完成')
def create_stair():
print('开始创建电梯')
print('正在创建电梯')
print('创建电梯完成')
create_building()
开始创建房间 正在创建房间 创建房间完成 开始创建电梯 正在创建电梯 创建电梯完成二、4种函数的参数形式
# 1. 普通参数
def say_hi(name):
print(f'hello,{name}')
print('欢迎来到大熊课堂')
say_hi('JackMa')
def create_window(width,height):
print(f'窗口的宽是{width};高是{height}')
create_window(2,1)
# 2. 默认参数
def total(hour, salary=8):
print(f'今天的薪水是{hour * salary}元')
total(8) # 用默认值,不会报错
total(8, 10)
# 3. 关键字参数 解决函数传参顺序问题
def student(firstname, lastname):
print(f'firstname is {firstname};lastname is {lastname}')
student('andy', 'Feng')
student(lastname='Feng', firstname='andy')
# 4. 不定长参数 *args元组 **kwargs字典
def my_function(width, height, *args, **kwargs):
print(width)
print(height)
print(args)
print(kwargs)
my_function(2.3, 4.5, 'hello', 'welcome', 'to', 'daxiong', 'thankyou', lastname='Feng', firstname='andy')
hello,JackMa
欢迎来到大熊课堂
窗口的宽是2;高是1
今天的薪水是64元
今天的薪水是80元
firstname is andy;lastname is Feng
firstname is andy;lastname is Feng
2.3
4.5
('hello', 'welcome', 'to', 'daxiong', 'thankyou')
{'lastname': 'Feng', 'firstname': 'andy'}
三、函数返回值
# 例1:求圆的面积
pi = 3.14
def area(r):
return pi * (r ** 2)
print(area(2))
# 例2:将分钟转化为“时-分” 100分钟=1小时40分 1小时=60分钟 100/60
def transform_minute(minute):
hours = minute // 60
minutes = minute % 60
print(f'{minute}分钟可以转化为{hours}小时{minutes}分钟')
return hours, minutes
hours, minutes = transform_minute(200)
print(f"hours is {hours}")
print(f'200分钟可以转化为{hours}小时{minutes}分钟')
print(transform_minute(200))
12.56 200分钟可以转化为3小时20分钟 hours is 3 200分钟可以转化为3小时20分钟 200分钟可以转化为3小时20分钟 (3, 20)四、函数的作用域,全局/局部变量
# 全局变量
a = 1 # 不可变类型 想在函数内修改需要在前面加global
l = [1, 2, 3] # 可变类型 不用global类型就可以在函数内修改
def test1():
# a = 100 # 局部变量
global a
a += 1 # 修改全局变量
l.append(4)
print(l)
def test2():
# a = 300 # 局部变量
print(a)
test2()
test1()
print(a)
1 [1, 2, 3, 4] 2五、函数的嵌套
def test1():
a = 10
print('test1开始执行')
print(f'test1内部变量a的值是{a}')
def test2():
# 内部函数修改外部函数的值,需要加nonlocal函数
# 函数内部修改不可变全局变量,需要加global函数
nonlocal a
a = 100
print('test2开始执行')
print(f'test2内部变量a的值是{a}')
test2()
print(f'test1内部变量a的值是{a}')
test1()
# test2() # 不能调用,只能在内部
test1开始执行 test1内部变量a的值是10 test2开始执行 test2内部变量a的值是100 test1内部变量a的值是100六、函数的递归
大部分递归都可以用循环来代替
例子:算阶乘
def fact(n):
if n == 1:
return 1
result = n * fact(n-1)
return result
# 不能用太多递归次数,因为python用栈来存函数变量,如果函数太多,会导致栈溢出
result = fact(3)
print(result)
七、匿名函数lambda
lambda 形参: 函数体
(lambda 形参: 函数体)(实参)
# 常规函数
def add(x, y):
return x + y
result = add(1, 2)
print(result)
# lambda 表达式
expression = lambda x, y: x + y
print(expression(1, 2))
# lambda 简单形式
result = (lambda x, y: x + y)(1, 2)
print(result)
八、匿名函数lambda的应用
- 在列表推导式中
# 列表推导式
result = [x ** 2 for x in range(10)]
print(result)
# 列表推导式+函数
def multiple(x):
return x**2
print([multiple(x) for x in range(10)])
# 列表中使用lambda
print([(lambda x:x**2)(x) for x in range(10)])
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81] [0, 1, 4, 9, 16, 25, 36, 49, 64, 81] [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
- sort函数中,默认实参是列表中每个元素
# sort函数 -- 用函数作key def take_second(list_val): return list_val[1] list_value = [(5, 6), (7, 3), (1, 8)] list_value.sort(key=take_second) print(list_value) # sort函数 -- 用lambda作key list_value.sort(key=lambda x: x[1], reverse=True) print(list_value)
[(7, 3), (5, 6), (1, 8)] [(1, 8), (5, 6), (7, 3)]九、匿名函数和常规函数对比
匿名函数是表达式,常规函数是语句
匿名函数为了简化代码,如果只调用一次可以使用
# 不是函数式编程,因为同样的input,output不同
def doubler1(l):
for item in range(0, len(l)):
l[item] *= 2
return l
list_value = [1, 2, 3, 4, 5]
print(doubler1(list_value))
print(doubler1(list_value))
# 是函数式编程
def doubler2(l):
new_list = []
for item in l:
new_list.append(item * 2)
return new_list
list_value = [1, 2, 3, 4, 5]
print(doubler2(list_value))
print(doubler2(list_value))
[2, 4, 6, 8, 10] [4, 8, 12, 16, 20] [2, 4, 6, 8, 10] [2, 4, 6, 8, 10]十一、函数式编程map()、filter()、reduce()函数
- map()
# 方法一:函数
def doubler(x):
x *= 2
return x
list_val = [1, 2, 3, 4, 5]
result = map(doubler,list_val)
print(list(result))
# 方法二:lambda
result = map(lambda x: x * 2, list_val)
print(list(result))
- filter()
# 方法一:函数
def is_odd(x):
# if x % 2 == 1:
# return True
# else:
# return False
return x % 2 == 1
list_value = [1, 2, 3, 4, 5]
result = filter(is_odd,list_value)
print(list(result))
# 方法二:lambda
result = filter(lambda x: x % 2 == 1, list_value)
print(list(result))
- reduce()
from functools import reduce
# 方法一:函数
def add(x, y):
return x + y
list_value = [1, 2, 3, 4, 5]
result = reduce(add,list_value)
print(result)
# 方法二:lambda
result = reduce(lambda x, y: x + y, list_value)
print(result)
十二、函数式编程map() VS 列表推导式
- 形式上对比:
- 效率上对比:
列表推导式: 0-99个元素,一次性全部输出,占用内存大
map: 循环一次,输出一次,占用的内存小,效率更高
import timeit
list_time = timeit.timeit('[str(i) for i in range(100)]', number=10000)
print(list_time)
map_time = timeit.timeit('map(str,range(100))', number=10000)
print(map_time)
map_list_time = timeit.timeit('list(map(str,range(100)))', number=10000)
print(map_list_time)
0.150411083 0.0024872499999999964 0.126015125
- 总结
# 1. 赋值
def func(message):
print(f"Got a message:{message}")
send_message = func
send_message("welcome to DaXiong course") # func("welcome to DaXiong course")
# 2. 作为参数
def get_message(message):
return f"Got a message:{message}"
def call(func, message):
print(func(message))
call(get_message, "welcome to DaXiong course")
# 3. 支持嵌套
def func(message):
def get_message(message):
print(f"Got a message:{message}")
return get_message(message)
func("welcome to DaXiong course")
# 4. 返回值
def func():
def get_message(message):
return f"Got a message:{message}"
return get_message
send_message = func() # send_message = get_message
message_string = send_message("welcome to DaXiong course") # get_message()
print(message_string)
Got a message:welcome to DaXiong course Got a message:welcome to DaXiong course Got a message:welcome to DaXiong course Got a message:welcome to DaXiong course十三、函数装饰器
import time
def my_decorator(func):
def wrapper():
print("wrapper函数开始")
start_time = time.perf_counter()
func()
end_time = time.perf_counter()
print(f"函数运行时间:{end_time - start_time}")
print("wrapper函数结束")
return wrapper
@my_decorator
def for_loop():
print("for_loop函数开始")
for i in range(10000):
pass
print("for_loop函数结束")
@my_decorator
def while_loop():
print("while_loop函数开始")
i = 0
while i < 10000:
i+=1
print("while_loop函数结束")
# new_for = my_decorator(for_loop) # wapper
# new_for()
for_loop() # 相当于wapper()
# new_while = my_decorator(while_loop)
# new_while()
while_loop() # 相当于wapper()
wrapper函数开始 for_loop函数开始 for_loop函数结束 函数运行时间:0.00021966699999999978 wrapper函数结束 wrapper函数开始 while_loop函数开始 while_loop函数结束 函数运行时间:0.0004706249999999988 wrapper函数结束十三、带参数的函数装饰器
import time
def my_decorator(func):
def wrapper(number):
print("wrapper函数开始")
start_time = time.perf_counter()
func(number)
end_time = time.perf_counter()
print(f"函数运行时间:{end_time - start_time}")
print("wrapper函数结束")
return wrapper
@my_decorator
def for_loop(number):
print("for_loop函数开始")
for i in range(number):
pass
print("for_loop函数结束")
@my_decorator
def while_loop(number):
print("while_loop函数开始")
i = 0
while i < number:
i += 1
print("while_loop函数结束")
# new_for = my_decorator(for_loop) # wapper
# new_for(100000) # wapper(100000)
for_loop(100000) # 相当于wapper(100000)
# new_while = my_decorator(while_loop)
# new_while()
while_loop(100000) # 相当于wapper(100000)
wrapper函数开始 for_loop函数开始 for_loop函数结束 函数运行时间:0.002143875 wrapper函数结束 wrapper函数开始 while_loop函数开始 while_loop函数结束 函数运行时间:0.004666666999999999 wrapper函数结束十三、不定长参数的函数装饰器
import time
import functools
def my_decorator(func):
@functools.wraps(func) # 原函数的元信息拷贝的装饰器里,否则print(welcome)结果是wrapper
def wrapper(*args, **kwargs):
print("wrapper函数开始")
start_time = time.perf_counter()
func(*args, **kwargs)
end_time = time.perf_counter()
print(f"函数运行时间:{end_time - start_time}")
print("wrapper函数结束")
return wrapper
@my_decorator
def welcome(*args, **kwargs):
name, gender = args
# if gender == "男":
# gender = "先生"
# else:
# gender = "女士"
gender = "男士" if gender == "男" else "女士"
print(f"hi {name}{gender},welcome to daxiong course")
print(f"{name}的年龄:{kwargs['age']}")
print(f"{name}的爱好:{kwargs['hobby']}")
welcome("Andy", "男", age="18", hobby="basketball")
十四、防止被装饰的函数改变
print(welcome.__name__) # welcome or wrapper
如果装饰器中含有:
@functools.wraps(func) # 原函数的元信息拷贝的装饰器里,否则print(welcome)结果是wrapper
则输出welcome,否则输出wrapper
十五、函数装饰器的嵌套import functools
def decorator1(func):
@functools.wraps(func)
def wapper1(*args, **kwargs):
print("执行装饰器1")
func(*args, **kwargs) # wapper2()
return wapper1
def decorator2(func):
@functools.wraps(func)
def wapper2(*args, **kwargs):
print("执行装饰器2")
func(*args, **kwargs) # welcome()
return wapper2
@decorator1
@decorator2
def welcome(message):
print(message)
# new_welcome = decorator1(decorator2(welcome)) # 1 2 welcome的顺序
# # decorator2(welcome) = wapper new_welcome = wapper1
# new_welcome("welcome to daxiong course") # wapper1("welcome to daxiong course")
welcome("welcome to daxiong course")
执行装饰器1 执行装饰器2 welcome to daxiong course银行系统综合案例
import datetime
import prettytable as pt # 将二维数组的打印美化成表格
balance = 1000
history = []
# 小数点后不能超过2位
def validate(func):
def wrapper(*args, **kwargs):
amount = str(args[0])
# 123.456
index = amount.index(".")
if len(amount) - index - 1 > 2:
print("格式输入错误")
else:
func(*args, **kwargs)
return wrapper
@validate
def deposit(account):
global balance
balance += account
writeHistory(account, "存钱")
@validate
def withdraw(account):
global balance
if account > balance:
print("余额不足")
else:
balance -= account
writeHistory(account, "取钱")
def writeHistory(account, type):
# 时间与格式化
d = datetime.datetime.now()
create_time = d.strftime("%Y-%m-%d %H:%M:%S")
if type == "存钱":
money = f"+{account}"
elif type == "取钱":
money = f"-{account}"
l = [create_time, type, money, "人民币", balance]
history.append(l)
def printHistory():
# print(history)
newHistory = pt.PrettyTable()
newHistory.field_names = ["交易日期", "摘要", "金额", "币种", "余额"] # 设置表格头
# newHistory.align["交易日期"] = "l"
# newHistory.align["摘要"] = "r"
# newHistory.align["币种"] = "l"
for his in history:
newHistory.add_row([his[0], his[1], his[2], his[3], his[4]])
print(newHistory)
def show_menu():
info = '''
*** 作菜单
0:退出
1:存款
2:取款
3:打印交易信息
'''
print(info)
while True:
show_menu()
number = int(input("请根据菜单编号输入:"))
if number == 0:
print("退出")
break
elif number == 1:
print("存钱")
depositMoney = float(input("请输入要存贮的金额:"))
deposit(depositMoney)
elif number == 2:
print("取钱")
withdrawMoney = float(input("请输入要存贮的金额:"))
withdraw(withdrawMoney)
elif number == 3:
print("查看交易日志")
printHistory()
else:
print("输入错误")
import prettytable as pt
# step1: 建立对象
table = pt.PrettyTable()
# step2: 设置表格头
table.field_names = ["交易日期", "摘要", "金额", "币种", "余额"]
# step3: 设置对齐方式
table.align["交易日期"] = "l"
table.align["摘要"] = "r"
table.align["币种"] = "l"
# step4: 添加行内元素
for his in history:
table.add_row([his[0], his[1], his[2], his[3], his[4]])
print(table)
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)