黑马程序员Python(续)
文章目录 52综合案例(暂时不学)-----------------------------------------------------------------------------以下是Python高级技巧编程----------------------------------------------53 闭包53.1 一个简单的闭包例子:53.2 总结: 54 装饰器54.1 案例介绍54.2 装饰器的作用:54.3 总结: 55 设计模式55.1 单例模式55.2 工厂模式 56 多线程56.1 进程56.2 线程56.3 多任务运行56.4 多线程运行56.5 进程与线程的注意点:56.6 并行执行56.7 以上内容总结56.8 多线程编程56.9 在创建多个线程时args和kwargs的传参方式59.10 多线程编程总结 57 网络编程58 正则表达式59 递归 52综合案例(暂时不学) -----------------------------------------------------------------------------以下是Python高级技巧编程---------------------------------------------- 53 闭包 目标使用一个全局变量account_amount来记录余额: account_amount = 0 def atm(num,deposit = True): global account_amount if deposit: account_amount += num print(f"存款:+{num},账户余额:{account_amount}") else: account_amount -= num print(f"存款:-{num},账户余额:{account_amount}") atm(300) atm(300) atm(100,False) 以上代码存在问题: 代码在命名空间上(变量定义)不够干净、整洁 全局变量有被修改的风险 将代码改为以下: def account_create(initial_amount=0): def atm(num,deposit = True): if deposit: initial_amount += num print(f"存款:+{num},当前余额:{initial_amount}") else: initial_amount -= num print(f"存款:+{num},当前余额:{initial_amount}") return atm atm = account_create() atm(10) atm(10) atm(10) atm(10) atm(6, deposit=False) 这样会报错: Traceback (most recent call last): File "D:/0000***/***/测试.py", line 382, in module atm(10) File "D:/0000***/***/测试.py", line 374, in atm initial_amount += num UnboundLocalError: local variable 'initial_amount' referenced before assignment 得添加nonlocal initial_amount,即: def account_create(initial_amount=0): def atm(num,deposit = True): # nonlocal initial_amount if deposit: initial_amount += num print(f"存款:+{num},当前余额:{initial_amount}") else: initial_amount -= num print(f"存款:+{num},当前余额:{initial_amount}") return atm atm = account_create() atm(10) atm(72) atm(26,deposit=False) atm(4) atm(6, deposit=False) 输出: 存款:+10,当前余额:10 存款:+72,当前余额:82 存款:+26,当前余额:56 存款:+4,当前余额:60 存款:+6,当前余额:54 53.1 一个简单的闭包例子: def outer(logo): def inner(msg): print(f"{logo}{msg}{logo}") return inner func1 = outer("黑马程序员") func1("大家好") func2 = outer("传智教育") func2("大家好") 输出: 黑马程序员大家好黑马程序员 传智教育大家好传智教育 解释:对于inner函数来说变量logo是外部变量,对于outer函数来说变量logo是临时变量 目标:对于函数inner来说,它依赖的外部变量一直都没有变化,又不想这个外部变量不会被改变 一种想法:在inner中是否可以修改变量logo的值呀? 实现方法:使用nonlocal这个关键字去修饰外部函数的变量才能在内部函数中修改它,即修改外部变量 代码: def outer(num1): def inner(num2): nonlocal num1 num1 += num2 print(num1) return inner func1 = outer(10) func1(10) func1(10) 输出: 20 30 53.2 总结: 54 装饰器 54.1 案例介绍 def sleep(): import time import random print("睡觉中....") time.sleep(random.randint(1,5)) 在不改变sleep函数功能以及函数体的前提下为sleep增加新功能 新功能描述: 在睡眠之前先”打印一下要睡觉了“ 在睡眠之后“打印一下要起床了” 内包写法: def outer(func): def inner(): print("我要睡觉啦") func() print("我要起床啦") return inner def sleep(): import time import random print("睡觉中....") time.sleep(random.randint(1,5)) inn = outer(sleep) inn() 装饰器写法: def outer(func): def inner(): print("我要睡觉啦") func() print("我要起床啦") return inner @outer def sleep(): import time import random print("睡觉中....") time.sleep(random.randint(1,5)) sleep() 54.2 装饰器的作用: 在不改变目标函数的同时增加额外的功能 54.3 总结: 55 设计模式 55.1 单例模式 创建一个tool.py文件 代码: class Tools(): pass t1 = Tools() t2 = Tools() print(id(t1)) print(id(t2)) 输出: D:\Anaconda3\python.exe "D:/0000***/***/tool.py" 2277989643456 2277989508864 进程已结束,退出代码为 0 表示这是两个不同的类对象 再创建一个测试.py文件 代码内容: from tool import t3 t4 = t3 t5 = t3 print(id(t4)) print(id(t5)) 输出: D:\Anaconda3\python.exe "D:/0000***/***/测试.py" 2747203220432 2747203220432 进程已结束,退出代码为 0 某些场景下才需要使用单例设计模式,不是所有情况下都是用单例模式 总结: 55.2 工厂模式 什么是工厂模式? 以上是基于原生的创造对象的方法 示例代码: class Person(): pass class Worker(Person): pass class Student(Person): pass class Teacher(Person): pass class PersonFactory(): def get_person(self,p_type): if p_type == "w": return Worker() elif p_type == "s": return Student() else: return Teacher() pf = PersonFactory() worker = pf.get_person("w") student = pf.get_person("s") teacher = pf.get_person("t") 总结: 前两条好处是重点 56 多线程 了解什么是进程、线程? 了解什么是并行执行? 现代操作系统如Mac OS X,UNIX,Linux,Windows等,都是支持“多任务”的操作系统 56.1 进程 进程就是一个程序,运行在系统之上,那么便称这个程序为一个运行进程,并分配进程ID方便系统管理 56.2 线程 线程就是归属于进程的,一个进程可以开启多个线程,执行不同的的工作,是进程的实际工作单位 类比: 进程好比一家公司,是操作系统对程序进行运行管理的单位 线程好比是公司的员工,进程可以有多个线程(员工),是进程实际的工作者 56.3 多任务运行 操作系统中可以运行多个进程,即多任务运行 56.4 多线程运行 一个进程内可以运行多个线程,即多线程运行 56.5 进程与线程的注意点: 进程之间是内存隔离的,即不同的进程拥有各自的内存空间。这就类似于不同的公司拥有不同的办公场所 线程之间是内存共享的,线程是属于进程的,一个进程的多个线程之间是共享这个进程所拥有的内存空间的。这就好比公司员工之间是共享公司的办公场所 56.6 并行执行 并行执行的意思指的是同一时间做不同的工作 进程之间就是并行执行的,操作系统可以同时运行好多程序,这些程序都是在并行执行 除了进程之外,线程其实也是可以并行执行的,比如一个python程序,完全可以做到: 一个线程在输出:你好 一个线程在输出:hello 像这样一个程序在同一时间做两件乃至多件不同的事情,我们称之为:多线程并行执行 56.7 以上内容总结 见以下图片内容 56.8 多线程编程 目标:掌握使用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 time import threading def sing(): while True: print("我在唱歌,啦啦啦...") time.sleep(1) def dance(): while True: print("我在跳舞,嘟嘟嘟...") time.sleep(1) if __name__ == '__main__': # 创建一个唱歌的线程 sing_thread = threading.Thread(target=sing) # 创建一个跳舞的线程 dance_thread = threading.Thread(target=dance) #启动多个线程 同时执行 sing_thread.start() dance_thread.start() 输出: 我在唱歌,啦啦啦... 我在跳舞,嘟嘟嘟... 我在唱歌,啦啦啦...我在跳舞,嘟嘟嘟... 我在跳舞,嘟嘟嘟...我在唱歌,啦啦啦... 我在唱歌,啦啦啦...我在跳舞,嘟嘟嘟... 我在跳舞,嘟嘟嘟...我在唱歌,啦啦啦... 我在跳舞,嘟嘟嘟...我在唱歌,啦啦啦... 等等... 56.9 在创建多个线程时args和kwargs的传参方式 import time import threading def sing(msg): while True: print(msg) time.sleep(1) def dance(msg): while True: print(msg) time.sleep(1) if __name__ == '__main__': # 创建一个唱歌的线程 给sing函数以args元组的方式传参 sing_thread = threading.Thread(target=sing,args=("我在唱歌,啦啦啦",)) # 创建一个跳舞的线程 给dance函数以kwargs字典的方式传参 dance_thread = threading.Thread(target=dance,kwargs={"msg":"我在跳舞,呱呱呱"}) #启动多个线程 同时执行 sing_thread.start() dance_thread.start() 输出: 我在唱歌,啦啦啦 我在跳舞,呱呱呱 我在跳舞,呱呱呱我在唱歌,啦啦啦 我在跳舞,呱呱呱我在唱歌,啦啦啦 我在唱歌,啦啦啦我在跳舞,呱呱呱 我在唱歌,啦啦啦我在跳舞,呱呱呱 等等... 59.10 多线程编程总结 1.threading 模块的使用: # 创建线程对象 tread_obj = threading.Thread(target = func) # 启动线程执行 thread_obj.start() 2.如何调参 args和kwargs 57 网络编程 58 正则表达式 59 递归