> 文章列表 > 黑马程序员---Python高级技巧编程

黑马程序员---Python高级技巧编程

黑马程序员---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 总结:

黑马程序员---Python高级技巧编程

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 总结:

黑马程序员---Python高级技巧编程

55 设计模式

55.1 单例模式

黑马程序员---Python高级技巧编程
黑马程序员---Python高级技巧编程
黑马程序员---Python高级技巧编程
创建一个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

某些场景下才需要使用单例设计模式,不是所有情况下都是用单例模式

总结:

黑马程序员---Python高级技巧编程

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")

总结:
黑马程序员---Python高级技巧编程
前两条好处是重点

56 多线程

了解什么是进程、线程?
了解什么是并行执行?
现代操作系统如Mac OS X,UNIX,Linux,Windows等,都是支持“多任务”的操作系统

56.1 进程

进程就是一个程序,运行在系统之上,那么便称这个程序为一个运行进程,并分配进程ID方便系统管理

56.2 线程

线程就是归属于进程的,一个进程可以开启多个线程,执行不同的的工作,是进程的实际工作单位

类比:
进程好比一家公司,是操作系统对程序进行运行管理的单位
线程好比是公司的员工,进程可以有多个线程(员工),是进程实际的工作者

56.3 多任务运行

操作系统中可以运行多个进程,即多任务运行

56.4 多线程运行

一个进程内可以运行多个线程,即多线程运行

56.5 进程与线程的注意点:

进程之间是内存隔离的,即不同的进程拥有各自的内存空间。这就类似于不同的公司拥有不同的办公场所
线程之间是内存共享的,线程是属于进程的,一个进程的多个线程之间是共享这个进程所拥有的内存空间的。这就好比公司员工之间是共享公司的办公场所
黑马程序员---Python高级技巧编程

56.6 并行执行

并行执行的意思指的是同一时间做不同的工作
进程之间就是并行执行的,操作系统可以同时运行好多程序,这些程序都是在并行执行
除了进程之外,线程其实也是可以并行执行的,比如一个python程序,完全可以做到:
一个线程在输出:你好
一个线程在输出:hello
像这样一个程序在同一时间做两件乃至多件不同的事情,我们称之为:多线程并行执行

56.7 以上内容总结

见以下图片内容黑马程序员---Python高级技巧编程

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