python函数

python函数,第1张

python函数

文章目录

一、函数的定义二、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("输入错误")

prettytable将二维数组的打印美化成表格
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)

欢迎分享,转载请注明来源:内存溢出

原文地址: https://www.outofmemory.cn/zaji/5720743.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-18

发表评论

登录后才能评论

评论列表(0条)

保存