Python – 高阶使用基础

闭包

基础概念

在Python中,闭包就是定义一个双层嵌套函数,内层函数可以访问外层函数的变量,将内层函数作为处层函数的返回,此内层函数就是闭包函数

问题案例:把一个ATM取款作为一个模块,提供一个存取款的方法:

# 闭包
account_amount = 0


# 定义一个方法,它用于存取款
# is_saveMoney 是否存款
def atm(num, is_saveMoney=True):
    global account_amount
    if is_saveMoney:
        account_amount += num
        print(f"当前存入{num}元,账号总计为{account_amount}元")
    else:
        account_amount -= num
        print(f"当前取款{num}元,账号总计为{account_amount}元")


atm(100)  # 当前存入100元,账号总计为100元
atm(100)  # 当前存入100元,账号总计为200元
atm(200)  # 当前存入200元,账号总计为400元
atm(100, is_saveMoney=False)  # 当前取款100元,账号总计为300元

从上面的代码我们看出了问题,当这作为一个模块时,account_amount 是可以被外部代码所引入并进行修改的,对于业务逻辑来说是不合理的,因为账户金额不应该被允许引入和修改。这是因为,account_amount在这里已经成为了一个全局变量,若我们有两个人以上对atm操作的话,必然会使account_amount的值发生混乱。

 

通过定义闭包,把临时变量作为方法中的一员,每一位调用该方法的人,都应该创建一个只属于他自己使用的临时变量,每个人只能使用属于他自己的变量,这时我们可以使用闭包,通过嵌套方法来实现变量的私有化

def create_account(account_amount=0):
    def atm(num, is_save_money=True):
        nonlocal account_amount
        if is_save_money:
            account_amount += num
            print(f"当前存入{num}元,账号总计为{account_amount}元")
        else:
            account_amount -= num
            print(f"当前取出{num}元,账号总计为{account_amount}元")

    return atm


atm = create_account()  # 调用外层方法返回内层atm方法,同时定义了临时变量account_amount
atm(100)  # 当前存入100元,账号总计为100元
atm(100)  # 当前存入100元,账号总计为200元
atm(200)  # 当前存入200元,账号总计为400元
atm(100, is_save_money=False)  # 当前取出100元,账号总计为300元

 

nonlocal 关键字的作用

在闭包的内部函数中,若想有能力修改外部方法函数的变量值,就需要在使用该外部变量值的内部方法中使用nonlocal声明这个变量,那么内部方法就可以使用外部方法的变量了,如果不声明,则只能使用,不能修改

 

装饰器

装饰器其实也是一种闭包,其功能就是在不破坏目标函数原有的代码和功能的前提下,为目标函数增加新功能,有点类似Java的切面编程

针对闭包的与python的功能,我们可以把传入的临时变量可以是一个函数,通过传入一个函数,并在函数的调用前后进行功能增加

示例:

def outer(func):
    def inner():
        print("我要开始睡觉了")
        func()  # 调用接收回来的方法,在方法调用前后增加功能
        print("我要起床了")

    return inner


# 定义一个睡觉的方法
def sleep():
    import time
    import random
    print("我要睡觉了")
    time.sleep(random.randint(1, 5))


fn = outer(sleep)
fn()

 

 

针对这类对函数功能的扩展的闭包,Python提供了一种语法糖,可以直接使用【@外部闭包名】于需要增强功能的函数上,就可以实现函数功能的增强,无需传入参数等

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

 

 

设计模式(基础)

单例模式

在某些使用场境下,我们只希望在整个软件生命周期内,只需要出现某个类的一个实例,可以定义一个单例模式

# 单例模式
class StrTools:
    pass

strtools = StrTools()

 

 

 

工厂模式

工厂模式,在Python 中是指可以定义一个方法或类,去统一化创建多个不同的对象,这样可以有效的解耦,当业务代码中出现需要修改时,我们可以直接在工厂类中修改,而免除在业务代码中大量修改的情况:

# 工厂模式

class Person:
    pass


class Student(Person):
    pass


class Teacher(Person):
    pass


class Manager(Person):
    pass


class Factory:
    def create_person(self, type):
        if type == "Student":
            return Student()
        elif type == "Teacher":
            return Teacher()
        else:
            return Manager()

# 使用工厂类调用工厂方法实现使用一个方法创建多个类对象
factory = Factory()
stu = factory.create_person("Student")
tea = factory.create_person("Teacher")
man = factory.create_person("Manager")

 

 

多线程(基础)

引入包

Python 中提供了一种用于多线程执行的包,Threading 模块

语法:

import threading

thread_obj = threading.Thread([group [, target [, name [, args [, kwargs]]]]])

 

  • group: 暂时无用,未来功能的预留参数
  • target: 执行的目标任务名
  • args: 以元组的方式给执行任务传参
  • kwargs: 以字典方式给执行任务传参
  • name: 线程名,一般不用设置

启动线程

thread_obj.start()

 

 

示例:

import threading
import time


def sing(msg):
    while True:
        print(msg)
        time.sleep(1)


def dance(msg):
    while True:
        print(msg)
        time.sleep(0.5)


if __name__ == '__main__':
    t1 = threading.Thread(target=sing, kwargs={"msg":"我在唱歌"})
    t2 = threading.Thread(target=dance, kwargs={"msg":"我在跳舞"})
    t1.start()
    t2.start()

 

 

网络编程(基础)

Socket

socket 是进程之间通信的工具,进程之间想要进行网络通讯需要socket

服务端

要在Py中创建一个服务端,只需要几个步骤就可以

  • 1.创建socket对象(未区分服务端还是客户端)
  • import socket
    socket_server = socket.socket()
  • 2.绑定socket_server到指定ip地址端口
  • # 定义服务端ip与端口
    socket_server.bind(('localhost', 1234))
  • 3.服务端开始监听端口
  • # 监听服务端,设置监听数为1
    socket_server.listen(1)
  • 4.接收客户端连接,获得连接对象
  • # 等待接收客户端的数据过来,会接收一个元组数据
    # socket_client 为当前客户端连接对象,通过对象进行回复操作
    # address 为当前客户端的连接信息
    socket_client, address = socket_server.accept()
    print(f"客户端对象:{socket_client},连接信息为:{address}")
  • 5.客户端连接后,通过recv方法,接收客户端发送的消息
  • # 接收客户端的数据,定义缓冲区大小为1024
    msg = socket_client.recv(1024).decode()
    print(f"发来消息:{msg}")
    
  • 6.通过socket_client(客户端当次连接对象),调用send方法可以回复消息
  • # 输入消息,转为bytes
    bytes_data = input("输入要回传的消息").encode("utf-8")
    # 发送消息
    socket_client.send(bytes_data)
  • 7.socket_client(客户端当次连接对象)和socket_server对象调用close方法,关闭连接
  • # 关闭服务
    socket_client.close()
    socket_server.close()

 

客户端

客户端的创建分别如下几步:

  • 1.创建socket对象
  • import socket
    client_socket = socket.socket()
  • 2.连接到服务端
  • client_socket.connect(("localhost", 1234))
  • 3.发送消息
  • msgBytes = input("请输入信息").encode("utf-8")
    client_socket.send(msgBytes)
  • 4.接收返回消息
  • msg = client_socket.recv(1024).decode("utf-8")
    print(f"收到信息:{msg}")
  • 5.关闭连接
  • client_socket.close()
    

正则表达式

使用单个字符串来描述、匹配某个句法规则的字符串,常被用来检索、替换那些符合某个模式的文本。

元字符匹配表

  • . -> 匹配任意1个字符(除了\n),\.匹配点自身
  • [] -> 匹配 [] 中列举的字符
  • \d -> 匹配数字,即0-9
  • \D -> 匹配非数字
  • \s -> 匹配空白,即空格、tab键
  • \S -> 匹配非空白
  • \w -> 匹配单词字符,即a-z、A-Z、0-9、_
  • \W -> 匹配非单词字符
  • 关于次数的定义
  • * -> 匹配前一个规则的字符出现0至无数次
  • + -> 匹配前一个规则的字符出现1到无数次
  • ? -> 匹配前一个规则的字符出现0次或1次
  • {m} -> 匹配前一个规则的字符出现m次
  • {m,} -> 匹配前一个规则的字符出现最少m次
  • {m,n} -> 匹配前一个规则的字符出现m到n次
  • 关于边界匹配
  • ^ -> 匹配字符串开头
  • $ -> 匹配字符串结尾
  • \b -> 匹配一个单词的边界
  • \B -> 匹配非单词边界
  • 分组匹配
  • | -> 匹配左右任意一个表达式
  • () -> 将括号中字符作为一个分组

注意:在Python中,使用 \ 符号有可能会引起转义,在我们写正则时,我们应该让正则的字符以普通字符显示而非转义功能性字符

# 在字符串前加上 r 则表示该字符串中不进行转义
str = r"[0-9a-zA-Z]"

 

match 从头匹配

使用match 会将文本从头部开始匹配,如果头部匹配不成功,则后面的不再考虑,返回None,如果匹配成功,则返回Result,可以通过调用span方法返回该匹配的范围

import re

str = "itheima1 @@python2 !!666 ##itcacast3"

# 从头开始匹配,匹配成功返回结果
print(re.match("[a-zA-Z]{1,4}", str))  # <re.Match object; span=(0, 4), match='ithe'>

 

 

search 搜索一个

search 可以搜索整个字符串,找出匹配的。但它只找一个,当在文本中找到后,就不再寻找了。

import re

str = "itheima1 @@python2 !!666 ##itcacast3"

# 全局匹配,匹配一个后就停止
print(re.search("[a-zA-Z]{1,4}", str))  # <re.Match object; span=(0, 4), match='ithe'>

 

 

findall 找到所有

findall 可以搜索整个字符串,并找出所有匹配的,并以列表方式返回

import re

str = "itheima1 @@python2 !!666 ##itcacast3"

# 全局匹配,匹配出所有
print(re.findall("[a-zA-Z]{1,4}", str))  # ['ithe', 'ima', 'pyth', 'on', 'itca', 'cast']

 

如果您喜欢本站,点击这儿不花一分钱捐赠本站

这些信息可能会帮助到你: 下载帮助 | 报毒说明 | 进站必看

修改版本安卓软件,加群提示为修改者自留,非本站信息,注意鉴别

THE END
分享
二维码
打赏
海报
Python – 高阶使用基础
闭包 基础概念 在Python中,闭包就是定义一个双层嵌套函数,内层函数可以访问外层函数的变量,将内层函数作为处层函数的返回,此内层函数就是闭包函数 问题案例:把一个ATM取款作为一个模块,……
<<上一篇
下一篇>>