一、函数的定义二、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条)