Python基础(十)——闭包、装饰器、设计模式与多线程编程
十一.高级用法
1.闭包
在函数嵌套的前提下,内部函数使用了外部函数的变量,并且外部函数返回了内部函数,把这个使用外部函数变量的内部函数称为闭包。
解释:
外部函数的参数因为作用域的原因,只是一个临时变量,调用完函数对于外部而言变量就消失了,而内部函数的作用域则为外部函数定义的区域。因此,把原本的全局变量作为参数放入外部函数中,成为局部变量,而该局部变量只能被内部函数访问,从而实现变量的安全化。
适用于:依赖外部全局变量,但是不希望全局变量被访问而修改的情况。
缺点:
由于内部函数持续引用外部函数的值,导致这部分内存空间不被释放,一直占用内存。
# 简单的闭包
def outer(num1):
def inner(num2):
print(num1+num2)
return inner # 返回值为内部函数
f1 = outer(50) # f1接收的为一个函数
f1(20)
"""
返回值:
70
"""
# 使用nonlocal关键字修饰外部函数
def outer(num1):
def inner(num2):
nonlocal num1
# 使用nonlocal关键字修饰外部函数的变量,才可以在内部函数中修改它
num1 = 200
print(num1+num2)
return inner # 返回值为内部函数
f1 = outer(50) # f1接收的为一个函数
f1(20)
"""
返回值:
220
"""
# 闭包实现ATM机
def outer(all_money = 0):
def inner(money, flag=True):
nonlocal all_money
if flag:
all_money += money
print(f"成功存款{money}元,账户余额为{all_money}元")
else:
all_money -= money
print(f"成功取款{money}元,账户余额为{all_money}元")
return inner
account = outer()
account(2000, True)
account(500, False)
"""
返回值:
成功存款2000元,账户余额为2000元
成功取款500元,账户余额为1500元
"""
2.装饰器
装饰器也是一种闭包,其功能是在不破坏目标函数原有代码和功能的前提下,为目标函数增加新功能。
- 一般写法:(闭包写法)执行逻辑
定义闭包函数,函数内部包括:执行目标函数、添加新的功能
import random
import time
def outer(func):
def inner():
print("我困死要睡觉了") # 新的功能
func() # 执行目标函数
print("我不得不起床了") # 新的功能
return inner
def sleep(): # 目标函数
print("睡觉中……勿扰……")
time.sleep(random.randint(1, 10))
fun = outer(sleep)
fun()
"""
返回:
我困死要睡觉了
睡觉中……勿扰……
我不得不起床了
"""
- 语法糖写法
使用@外部函数,定义在目标函数之上。把sleep函数作为参数传入outer函数,返回inner函数执行了操作逻辑。
import random
import time
def outer(func):
def inner():
print("我困死要睡觉了")
func()
print("我不得不起床了")
return inner
# @外部函数,定义在目标函数之上
@outer
def sleep():
print("睡觉中……勿扰……")
time.sleep(random.randint(1, 10))
sleep()
"""
返回值:
我困死要睡觉了
睡觉中……勿扰……
我不得不起床了
"""
3.设计模式
是一种编程套路思想,面向对象也属于设计模式的一种。
设计模式有多种,可以深入学习。此处仅介绍基础常用的单例模式和工厂模式。
- 单例模式
某些场景下,需要一个类无论获取多少次类对象,都仅仅提供一个具体的实例,用以节省类对象的开销和内存开销,比如某些工具类,仅需要一个实例,即可在各处使用。
【保证一个类只有一个实例,并提供一个访问它的全局访问点】
使用方式:
在一个文件中定义该类并获得类对象,在另一个文件中通过import导入类对象。
# test.py
class tools:
pass
my_tool = tools()
# main.py
from test import my_tool
t1 = my_tool
t2 = my_tool
t3 = my_tool
print(id(t1))
print(id(t2))
print(id(t3))
# t1、t2、t3是同一个对象,地址相同
"""
返回值:
2146066533584
2146066533584
2146066533584
"""
- 工厂模式
当需要大量创建一个类的实例时,从原生的使用类的构造去创建对象的形式。
优点:
大批量创建对象时有统一的入口,易于维护;
当发生修改时,仅修改工厂类的创建方法即可;
class Phone:
pass
class HuaWei(Phone):
pass
class XiaoMi(Phone):
pass
class Honour(Phone):
pass
class PhoneFactory:
def get_phone(self, phone_type):
if phone_type == '1':
return HuaWei()
elif phone_type == '2':
return XiaoMi()
else:
return Honour()
pf = PhoneFactory()
phone1 = pf.get_phone('1')
phone2 = pf.get_phone('2')
phone = pf.get_phone('3')
4.进程与线程
**进程:**一个程序运行在系统上则称该程序为一个进程,分配ID方便系统管理。操作系统中可以运行多个进程,即多任务运行。
**线程:**归属于进程,是进程实际工作的最小单位,执行不同的工作。一个进程可以开启多个线程,即多线程运行。
**注意:**进程之间是内存隔离的,不同的进程拥有各自的内存空间。
线程之间是内存共享的,线程是属于进程的,一个进程内的多个线程之间共享进程拥有的内存。
**并行执行:**同时执行不同的工作,进程之间是并行执行的,线程之间也是。
5.多线程
使用threading模块实现。
- 单线程
import time
def sing():
while True:
print("唱歌")
time.sleep(1)
def dance():
while True:
print("跳舞")
time.sleep(1)
if __name__ == '__main__':
sing()
dance()
"""
输出:
唱歌
唱歌
唱歌
唱歌
唱歌
唱歌
唱歌
……
"""
- 多线程
import threading
import time
def sing():
while True:
print("唱歌")
time.sleep(1)
def dance():
while True:
print("跳舞")
time.sleep(1)
"""
thread = threading.Thread(group= , target= , name=, args= , kwargs=)
-group: 未来功能的预留参数
-target: 执行的目标任务名
-name: 线程名,一般不用设置
-args: 以元组形式给执行任务传参
-kwargs: 以字典形式给执行任务传参
"""
if __name__ == '__main__':
# 创建唱歌跳舞的线程
sing_thread = threading.Thread(target=sing)
dance_thread = threading.Thread(target=dance)
# 线程工作
sing_thread.start()
dance_thread.start()
"""
输出:
唱歌
跳舞
跳舞唱歌
唱歌跳舞
唱歌跳舞
唱歌跳舞
唱歌
跳舞
唱歌跳舞
唱歌跳舞
唱歌跳舞
…………
"""
import threading
import time
def sing(msg):
while True:
print(msg)
time.sleep(1)
def dance(msg):
while True:
print(msg)
time.sleep(1)
if __name__ == '__main__':
# 创建唱歌跳舞的线程
sing_thread = threading.Thread(target=sing, args=("唱歌啦……",))
dance_thread = threading.Thread(target=dance, kwargs={"msg": "跳舞啦……"})
# 线程工作
sing_thread.start()
dance_thread.start()
"""
输出:
唱歌啦……跳舞啦……
跳舞啦……唱歌啦……
唱歌啦……跳舞啦……
唱歌啦……跳舞啦……
跳舞啦……
唱歌啦……
唱歌啦……跳舞啦……
…………
"""
【记录学习过程的笔记,欢迎大家一起讨论,会持续更新】
原文地址:https://blog.csdn.net/m0_74556076/article/details/142345960
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!