Python进阶

Python进阶

一、闭包

在定义全局变量上,全局变量有被修改的风险,一个包中的变量可能被其他的模块修改,因此需要闭包

def outer(logo):
    def inner(msg):
        print(f"<{logo}>{msg}<{logo}>")

    return inner		# 将函数返回出去


fn1 = outer("黑马程序员")	# fn1就是函数inner
fn1("hello")
#--------输出结果----------
<黑马程序员>hello<黑马程序员>
def outer(num1):
    def inner(num2):
        nonlocal num1  # 使用nonlocal关键字可以使内部函数修改外部函数
        num1 += num2
        print(num1)

    return inner


fn = outer(10)
fn(10)
fn(10)
fn(10)
#--------输出结果----------
20
30
40

优点:

  • 无需定义全局变量即可实现通过函数持续的访问、修改某个值
  • 闭包使用的变量的所用于在函数内,难以被错误的调用修改

缺点:

  • 由于内部函数持续引用外部函数的值,所以会导致这一部分内存空间不被释放,一直占用内存

二、设计模式

2.1 装饰器模式

装饰器是一种闭包,其功能就是izai不破坏目标函数原有的代码功能的前提下,为目标函数增加新功能

1、闭包写法

def outer(func):
    def inner():
        print("我睡觉了")
        func()
        print("我起床了")

    return inner


def sleep():
    import random
    import time
    print("睡眠中。。。。。")
    s = random.randint(1, 5)
    print(s)
    time.sleep(s)


fn = outer(sleep)
fn()
#===========结果输出===========
我睡觉了
睡眠中。。。。。
4
我起床了

2、装饰器的快捷写法(语法糖)

def outer(func):
    def inner():
        print("我睡觉了")
        func()
        print("我起床了")

    return inner

@outer
def sleep():
    import random
    import time
    print("睡眠中。。。。。")
    s = random.randint(1, 5)
    print(s)
    time.sleep(s)


sleep()
#==========结果输出============
我睡觉了
睡眠中。。。。。
3
我起床了

添加@注解的后面的参数是装饰器,即@符号和装饰函数和被装饰函数产生联系。即将被@标记的函数传入到@后面的函数中

2.2 单例模式

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

1、创建

class StrTools:
    pass

str_tool = StrTools()

2、使用

from strTools import str_tool

s1 = str_tool
s2 = str_tool

print(s1)
print(s2)
#==========结果输出============
<strTools.StrTools object at 0x01EAB310>
<strTools.StrTools object at 0x01EAB310>

2.3 工厂模式

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

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()
        elif p_type == 't':
            return Teacher()

factory = Factory()
work = factory.get_person('w')
student = factory.get_person('s')
teacher = factory.get_person('t')

三、多线程

创建方式:使用threading关键字

import threading

threading.Thread([group [,target[,name[,args [,kwargs]]]]])
#- group: 暂未使用,未来功能的预留函数
#- target: 执行的目标的任务名
#- args: 以元组的方式给执行任务传参
#- keargs: 以字典的方式给执行 的任务传参
#- name: 线程名,一般不需要设置

3.1 创建、启动线程

import time
import threading

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

def dance():
    while True:
        print("dance")
        time.sleep(1)

if __name__ == '__main__':
    # 创建线程1
    sing_thread = threading.Thread(target=sing)
    # 创建线程2
    dance_thread = threading.Thread(target=dance)

    # 启动线程
    sing_thread.start()
    dance_thread.start()
#==========结果输出============
sing
dance
dance
sing
sing
dance
singdance

3.2 传递参数

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__':
    # 创建线程1
    sing_thread = threading.Thread(target=sing, args=("Im sing",))  # 字符串后加逗号表示元组
    # 创建线程2
    dance_thread = threading.Thread(target=dance, kwargs={"msg": "Im dance"})

    # 启动线程
    sing_thread.start()
    dance_thread.start()
#==========结果输出============
Im sing
Im dance
Im dance
Im sing
Im sing
Im dance

四、网络编程

socket是进程之间通讯的工具,负责程序之间的网络数据传输

4.1 socket服务端

accept是一个阻塞方法

  • socket对象:用来设置监听、连接信息
  • accept对象:客户端的连接对象、客户端的地址信息

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Sjzify3T-1687274295589)(6、python进阶.assets/image-20230620222822933.png)]

使用socket创建对象后,可以使用创建的对象获取出客户端的IP和端口

import socket

# 1、创建socket对象
socket_server = socket.socket()
# 2、绑定ip地址和端口
socket_server.bind(("localhost", 8888))
# 3、监听端口
socket_server.listen(1)  # listen方法内接受一个参数,表示接受的连接数
# 4、等待客户端链接
result: tuple = socket_server.accept()
# accept方法返回的是二元元组(连接对象,客户端地址信息)
conn = result[0]  # 客户端的连接对象
address = result[1]  # 客户端的地址信息
# 可以通过 变量1,变量2 = socket_server.accept()的形式,直接接受二元元组的两个元素
# conn1, address1 = socket_server.accept()
# accept是一个阻塞方法
print(f"客户端信息是:{address}")
while True:
    # 5、接受客户端信息,使用客户端和服务端的连接对象,
    data: str = conn.recv(1024).decode("UTF-8")
    # recv接受的参数是缓冲区大小,一般给1024
    # recv方法返回的是一个字节数组,即bytes对象,不是字符串,可以使用decode进行解码
    print(f"客户端的消息是:{data}")
    # 6、发送消息,需要将字符串编码为字节数组对象
    msg = input("请输入需要回复的消息:")
    if msg == 'exit':
        break
    conn.send(msg.encode("UTF-8"))
# 7、关闭连接
conn.close()
socket_server.close()

4.2 socket客户端

import socket

# 1、创建socket对象
socket_client = socket.socket()
# 2、连接到服务端
socket_client.connect(("localhost", 8888))
while True:
    # 3、发送消息
    msg = input("请输入要给服务端的消息")
    if msg == 'exit':
        break
    socket_client.send(msg.encode("UTF-8"))
    # 4、接受返回消息
    recv_data = socket_client.recv(1024)  # 同样recv是阻塞的
    print(f"服务端返回的消息是:{recv_data.decode('UTF-8')}")
# 5、关闭连接
socket_client.close()
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值