黑马程序员---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 = 0def atm(num,deposit = True):global account_amountif deposit:account_amount += numprint(f"存款:+{num},账户余额:{account_amount}")else:account_amount -= numprint(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 += numprint(f"存款:+{num},当前余额:{initial_amount}")else:initial_amount -= numprint(f"存款:+{num},当前余额:{initial_amount}")return atmatm = 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 atminitial_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_amountif deposit:initial_amount += numprint(f"存款:+{num},当前余额:{initial_amount}")else:initial_amount -= numprint(f"存款:+{num},当前余额:{initial_amount}")return atmatm = 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 num1num1 += num2print(num1)return inner
func1 = outer(10)
func1(10)
func1(10)
输出:
20
30
53.2 总结:
54 装饰器
54.1 案例介绍
def sleep():import timeimport randomprint("睡觉中....")time.sleep(random.randint(1,5))
在不改变sleep函数功能以及函数体的前提下为sleep增加新功能
新功能描述:
在睡眠之前先”打印一下要睡觉了“
在睡眠之后“打印一下要起床了”
内包写法:
def outer(func):def inner():print("我要睡觉啦")func()print("我要起床啦")return inner
def sleep():import timeimport randomprint("睡觉中....")time.sleep(random.randint(1,5))inn = outer(sleep)
inn()
装饰器写法:
def outer(func):def inner():print("我要睡觉啦")func()print("我要起床啦")return inner@outer
def sleep():import timeimport randomprint("睡觉中....")time.sleep(random.randint(1,5))sleep()
54.2 装饰器的作用:
在不改变目标函数的同时增加额外的功能
54.3 总结:
55 设计模式
55.1 单例模式
创建一个tool.py文件
代码:
class Tools():passt1 = Tools()
t2 = Tools()print(id(t1))
print(id(t2))
输出:
D:\\Anaconda3\\python.exe "D:/0000*/*/tool.py"
2277989643456
2277989508864进程已结束,退出代码为 0
表示这是两个不同的类对象
再创建一个测试.py文件
代码内容:
from tool import t3t4 = t3
t5 = t3
print(id(t4))
print(id(t5))
输出:
D:\\Anaconda3\\python.exe "D:/0000*/*/测试.py"
2747203220432
2747203220432进程已结束,退出代码为 0
某些场景下才需要使用单例设计模式,不是所有情况下都是用单例模式
总结:
55.2 工厂模式
什么是工厂模式?
以上是基于原生的创造对象的方法
示例代码:
class Person():passclass Worker(Person):passclass Student(Person):passclass Teacher(Person):passclass 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 threadingdef 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 threadingdef 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 递归
递归: 即方法(函数)自己调用自己的一种特殊编程写法
如:
def func():if ...:func()return ...
函数自己调用自己,即称之为递归调用
递归需要注意:
1、注意退出的条件,否则容易编程无限递归
2、注意返回值的传递,确保从最内层,层层传递到最外层
os模块的3个方法:
os.listdir:
列出指定目录下的内容
os.path.isdir:
判断给定路径是否是文件夹,是返回True,否返回False
os.path.exists:
判断给定路径是否存在,存在返回True,否则返回False
import os
path = "D:\\goole下载的内容在此文件夹内"
# 返回指定的文件夹包含的文件或文件夹的名字的列表
print(os.listdir(path))# 如果指定的路径是现有目录,则返回True,否则返回False
path = "D:\\goole下载的内容在此文件夹内"
print(os.path.isdir(path))# 判断对象是否为一个目录
# os.path.exists()就是判断括号里的文件是否存在的意思,
# 括号内的可以是文件路径。
path = "D:\\goole下载的内容在此文件夹内\\嘿嘿.txt"
print(os.path.exists(path))
输出:
['-946787692-姓名-附件 (1).JPG',
'-946787692-姓名-附件 (2).JPG','-946787692-姓名-附件 (3).JPG', '-946787692-姓名-附件 (4).JPG', '-946787692-姓名-附件 (5).JPG', '-946787692-姓名-附件 (6).JPG', '-946787692-姓名-附件.JPG', '2022年普通招考博士研究生拟录取名单.xls', 'assignment.txt', 'pnas.1512080112 - 副本.docx', 'python组件.md', '《科幻世界》2016年全年合集-科幻世界.txt', '神经网络与深度学习-3小时.pptx', '附件:南方电网公司2022年校园招聘笔试大纲.pdf']
True
False