Python_高阶技巧

一、闭包

定义一个ATM功能的存取钱函数,通过全局变量account_amount来记录余额

Python_高阶技巧_第1张图片

尽管功能实现是ok的,但是仍有问题:

  • 代码在命名空间上(变量定义)不够干净、整洁 

  • 全局变量有被修改的风险

解决方式:将变量定义在函数内部是行不通的 --假如我的初始余额需要修改

我们需要使用闭包:

在函数嵌套的前提下,内部函数使用了外部函数的变量,并且外部函数返回了内部函数,我们把这个使用外部函数变量的内部函数称为闭包。

Python_高阶技巧_第2张图片

Python_高阶技巧_第3张图片

可以看出内部函数依赖外部函数的变量

如何在内部函数中修改外部函数变量的值 nonlocal

Python_高阶技巧_第4张图片

闭包注意事项:

优点,使用闭包可以让我们得到:

无需定义全局变量即可实现通过函数,持续的访问、修改某个值 

闭包使用的变量的所用于在函数内,难以被错误的调用修改  

缺点:

由于内部函数持续引用外部函数的值,所以会导致这一部分内存空间不被释放,一直占用内存(一般都是变量 占用不大)

"""

演示闭包

"""

# 简单闭包演示

def outer(logo):





    def inner(msg):

        print(f"<{logo}>{msg}<{logo}>")





    return inner





fn = outer("test")   # fn--确定了logo变量为test的inner函数

fn("bear")





# 使用闭包实现ATM存取功能

def outer_money(money=0):





    def inner_atm(num,deposit):

        nonlocal money        # 需要使用nonlocal关键字修饰外部函数的变量 才可在内部函数中修改它

        if deposit:

            money += num

            print(f"存款{num}元,余额{money}元")

        else:

            money -= num

            print(f"取款{num}元,余额{money}元")





    return inner_atm  # 必须要返回内部函数名 否则报错TypeError: 'NoneType' object is not callable





atm = outer_money(200)

atm(300,True)

二、装饰器 

装饰器其实也是一种闭包,在闭包函数内调用目标函数。 其功能就是在不破坏目标函数原有的代码和功能的前提下,为目标函数增加新功能。

Python_高阶技巧_第5张图片

1、装饰器的一般写法(闭包写法)

Python_高阶技巧_第6张图片

2、装饰器的快捷调用写法

Python_高阶技巧_第7张图片

三、设计模式

设计模式是一种编程套路,可以极大的方便程序的开发。最常见、最经典的设计模式,就是我们所学习的面向对象了。 除了面向对象外,在编程中也有很多既定的套路可以方便开发,我们称之为设计模式:

  • 单例、工厂模式

  • 建造者、责任链、状态、备忘录、解释器、访问者、观察者、中介、模板、代理模式 等等模式

1、单例模式

单例模式(Singleton Pattern)是一种常用的软件设计模式,该模式的主要目的是确保某个类只有一个实例存在。 在整个系统中,某个类只能出现一个实例时,单例对象就能派上用场。

 · 定义: 保证一个类只有一个实例,并提供一个访问它的全局访问点

 · 适用场景:当一个类只能有一个实例,而客户可以从一个众所周知的访问点访问它时。节省内存节省创建对象的开销

单例模式的实现:

Python_高阶技巧_第8张图片

class Str_Tools:

    pass

str_tool = Str_Tools()

from str_tool_class import str_tool

st1 = str_tool

st2 = str_tool

print(id(st1))

print(id(st2))

输出:

1942925989136

1942925989136

2、工厂模式

当需要大量创建一个类的实例的时候, 可以使用工厂模式。即,从原生的使用类的构造去创建对象的形式 迁移到,基于工厂提供的方法去创建对象的形式

"""

演示装饰器的写法

"""

# 1.装饰器的一般写法-

def outer(func):

    def inner():

        print("我要睡觉了")

        func()

        print("我起床了")





    return inner









def sleep():

    import random

    import time

    print("睡眠中.....")

    time.sleep(random.randint(1,5))





# fn = outer(sleep)

# fn()





# 2.装饰器的快捷写法-

def outer(func):

    def inner():

        print("我要睡觉了")

        func()

        print("我起床了")





    return inner





@outer

def sleep():

    import random

    import time

    print("睡眠中.....")

    time.sleep(random.randint(1,5))





sleep()

Python_高阶技巧_第9张图片

四、多线程 

1、进程、线程

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

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

进程 -好比一家公司,是操作系统对程序运行管理的单位

线程 -好比公司的员工,进程可以有多个线程(员工),是进程实际的工作者

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

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

注意点:

1.进程之间是内存隔离的,即不同的进程拥有各自的内存空间。这就类似于不同的公司拥有不同的办公场所

2.线程之间是内存共享的,线程是属于进程的,一个进程内的多个线程之间是贡献这个进程空间的。这就类似于公司员工之间是共分享办公场所的。

Python_高阶技巧_第10张图片

 2、并行执行

并行执行的意思指的是同一时间做不同的工作。

进程之间就是并行执行的,操作系统可以同时运行好多程序,即这些程序都是并行执行

除了进程以外,线程其实也可以并行执行的。比如一个Python程序,其实是完全可以做到;

  • 一个线程在输出:你好

  • 一个线程在输出:hello

像这样一个程序在同一时间做多件不同的事,就称之多线程并行执行

3、多线程编程  --threading模块

 Python的多线程可以通过threading模块来实现。

"""

演示工厂模式的创建实例

"""

class Person:

    pass





class Worker(Person):

    pass

class Student(Person):

    pass

class Teacher(Person):

    pass





class Factory:

    def get_person(self,p_type):

        if p_type == 'w':

            return Worker()

        elif p_type == 's':

            return Student()

        else:

            return Teacher()





factory = Factory()

worker = factory.get_person('w')

stu = factory.get_person('s')

teacher = factory.get_person('t')

Python_高阶技巧_第11张图片

需要传参的话可以通过:

  • args参数通过元组(按参数顺序)传参

  • kargs参数通过字典的形式传参

"""

演示多线程的使用

"""

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,args=("我要跳舞",))





    # 启动线程

    sing_thread.start()

    dance_thread.start()

五、网络编程 

1、socket网络编程;

socket简称套接字,是进程之间通信的一个工具,好比现实生活中的插座,所有的家用电器想要工作都是基于插座进行,进程之间想要进行网络通信需要socket

socket负责进程之间的网络数据传输,好比数据的搬运工

Python_高阶技巧_第12张图片

2、服务端和客户端

2个进程之间通过Socket进行相互通讯,就必须有服务端和客户端

Socket服务端:等待其他的进城连接、可以接受发来的消息、可以回复消息

Socket客户端:主动连接服务端、可以发送消息,可以接收回复

Python_高阶技巧_第13张图片

2.1 Socket服务端编程

步骤如下:

Python_高阶技巧_第14张图片

Python_高阶技巧_第15张图片

"""

演示Socket服务端开发

"""

import socket

# 创建Socket对象

socket_server = socket.socket()

# 绑定IP地址和端口

socket_server.bind(("localhost",8888))

# 监听端口

socket_server.listen(1)             # 整数参数表示接收连接的数量

# 等待客户端连接

# result = socket_server.accept()     # accept方法返回的是二元元祖(连接对象,客户端地址信息)

# conn = result[0]                    # 客户端和服务端的连接对象

# address = result[1]                 # 客户端的地址信息

conn,address = socket_server.accept()

# 注意:accept方法是阻塞的方法,等待客户端的连接,如果没有连接就卡在这一行不再向下执行

print(f"接受到了客户端的连接,客户端的信息是{address}")





while True:

    # 接收客户端信息 ,使用客户端和服务端的连接对象

    data = conn.recv(1024).decode("UTF-8")

    # recv -接受的参数是缓冲区的大小,一般1024即可

    # recv方法的返回值是一个字节数组也就是byte对象,可以通过decode方法使用utf-8编码将字节数组转换为字符串对象

    print(f"客户端发来的消息是:{data}")

    # 发送回复消息

    msg = input("请输入你要和客户端回复的消息:")  # encode可以将字符串编码为字节数组对象

    if msg == 'exit':

        break

    conn.send(msg.encode("UTF-8"))





# 关闭连接

conn.close()

socket_server.close()

2.1 Socket客户端编程

步骤如下:

Python_高阶技巧_第16张图片

Python_高阶技巧_第17张图片

"""

演示Socket客户端开发

"""

import socket





# 创建Socket对象

socket_client = socket.socket()

# 连接到服务端

socket_client.connect(("localhost",8888))





while True:

    # 发送消息

    msg = input("请输入要给服务端发送的消息:")

    if msg == 'exit':

        break

    socket_client.send(msg.encode("UTF-8"))

    # 接收返回消息

    recv_data = socket_client.recv(1024)        # recv是缓冲区大小,一般给1024,同样recv是阻塞的

    print(f"服务端回复的消息是:{recv_data.decode('UTF-8')}")

# 关闭连接

socket_client.close()

六、正则表达式

1、简述正则表达式

正则表达式,又称规则表达式(Regular Expression) 时使用单个字符串来描述、匹配某个语法规则的字符串,常被用来检索、替换那些符合某个模式(规则)的文本。

简单来说:正则表达式就是使用字符串定义规则,并通过规则去验证字符串是否匹配。

比如,验证一个字符串是否为符合条件的电子邮箱地址,只需要配置好正则规则,即可匹配任意邮箱。

比如通过正则规则: (^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$)  即可匹配一个字符串是否是标准邮箱格式。

如果不使用正则,使用if else来对字符串做判断就非常困难了。

2、正则表达式的三个基础方法

Python正则表达式,使用re模块,并基于re模块中的三个基础方法来做正则匹配

分别是:match、search、findall

2.1 re.match(匹配规则,被匹配字符串)

从被匹配字符串开头进行匹配,匹配成功返回匹配对象(包含匹配的信息--下标),匹配不成功,则返回None   

Python_高阶技巧_第18张图片

注意:假如开头没有满足匹配规则的对象,即使后面有也会返回None

2.2 search(匹配规则,被匹配的字符串)

搜索整个字符串,找出匹配的。从前向后,找到第一个后就停止,不再继续向后

Python_高阶技巧_第19张图片

2.3 findall(匹配规则,被匹配的字符串)

匹配整个字符串,找出全部匹配项

 Python_高阶技巧_第20张图片

"""

演示Python正则表达式re模块的3个基础匹配方法

"""

import re

s = "1pythonrning21bearupupythonread"





# match 从头匹配

result = re.match("21",s)

# print(result)

# print(result.span())

# print(result.group())





# search 搜索匹配

result1 = re.search("python",s)

print(result1)

print(result1.span(),result1.group())





# findall 搜索全部匹配

result2 = re.findall("python",s)

print(result2)

3、元字符匹配

3.1 单字符匹配

Python_高阶技巧_第21张图片

3.2 数量匹配

Python_高阶技巧_第22张图片

3.3 边界匹配

Python_高阶技巧_第23张图片

3.4 分组匹配

Python_高阶技巧_第24张图片

4、案例

  • 匹配账号,只能由字母和数字组成,长度限制6到10位规则为: ^[0-9a-zA-Z]{6, 10}$

  • 匹配QQ号,要求纯数字,长度5-11,第一位不为0 规则为:^[1-9][0-9]{4, 10}& [1-9]匹配      第一位,[0-9]匹配后面4到10位

  • 匹配邮箱地址,只允许qq、163、gmail这三种邮箱地址 规则为:^[\w-]+(\.              [\w-]+)*@(qq|163|gmail)(\.[\w-]+)+&

"""

演示Python正则表达式使用元字符进行匹配

"""

import re





# s = "ityuii@@python 22#d456opi\duhj2"

# result = re.findall('[0-9]',s)    # 字符串前面加上r标记表示字符串中的转义字符无效在,就是普通字符的意思

# print(result)





# 匹配账号,只能由字母和数字组成,长度限制6到10位

# r = '^[0-9a-zA-Z]{6,10}$'

# s = "1234567A_"

# print(re.findall(r,s))

# 匹配QQ号,要求纯数字,长度5-11,第一位不为0

# r = '^[1-9][0-9]{4,10}$'

# s = "24113A9"

# print(re.findall(r,s))

# 匹配邮箱地址,只能允许qq、163、gmail这三种邮箱的地址

# {内容}.{内容}.{内容}@{qq、163、gmail}.{}.{}..

r = r'(^[\w]+(\.[\w])*@(qq|163|gmail)(\.[\w]+)*$)'

s = "[email protected]"

print(re.match(r,s))

七、递归 重要的一种算法

递归:即方法(函数)自己调用自己的一种特殊的编程写法

递归注意点:

  • 注意退出的条件,否则容易变成无限递归

  • 注意返回值的传递,确保从最内层,层层传递到最外层

os模块的3个方法:

  • os.listdir,列出指定目录下的内容

  • os.path.isdir,判断给定路径是否是文件夹,是返回True,否返回False 

  • os.path.exists,判断给定路径是否存在,存在返回True,否则返回False

递归实现案例:

最典型的递归场景为找出一个文件夹中全部的文件。如图,在D:/test 文件夹内,有如下嵌套结构和所属的文件, 可以通过递归编程的形式完成

Python_高阶技巧_第25张图片

你可能感兴趣的:(开发语言,python)