Python第十三章

1.闭包

(1)

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


def outer(logo):
     def inner(msg):
         print(f"<{logo}>{msg}<{logo}>")
     return inner
f = outer("*")
f("hello")

# output: <*>hello<*>

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


def outer(num1):
     def inner(num2):
         nonlocal num1
         num1 += num2
         print(num1)

     return inner
f =outer(10)
f(10)
f(10)
# output: 
# 20
# 30

 eg:(atm)


def account_create(initial_amount=0):

    def atm(num, deposit=True):
        nonlocal initial_amount
        if deposit:
            initial_amount += num
            print(f"存款:+{num},账户余额:{initial_amount}")
        else:
            initial_amount -= num
            print(f"取款:-{num},账户余额:{initial_amount}")
    return atm

fn = account_create()
fn(200)
fn(300)
fn(300, deposit=False)

# 存款:+200,账户余额:200
# 存款:+300,账户余额:500
# 取款:-300,账户余额:200

(2)优点:

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

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

缺点:

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

2.装饰器

(1)也是一种闭包,功能是在不破坏目标函数原有的代码和功能的前提下,为目标函数增加新功能

一般写法:

eg:在调用sleep前输出:我要睡觉了,调用后输出:结束


def sleep():
    import random
    import time
    print("Zzz...")
    time.sleep(random.randint(1,5))

def outer(func):
    def inner():
        print("我要睡觉了...")
        func()
        print("结束")
    return inner

fn = outer(sleep)
fn()

# output:
# 我要睡觉了...
# Zzz...
# 结束

高级:



def outer(func):
    def inner():
        print("我要睡觉了...")
        func()
        print("结束")
    return inner

@outer
def sleep():
    import random
    import time
    print("Zzz...")
    time.sleep(random.randint(1,5))

sleep()
# output:
# 我要睡觉了...
# Zzz...
# 结束

3、设计模式

设计模式就是一种编程套路,使用特定的套路得到特定的效果

(1)单例模式

就是对一个类,只获取其唯一的类实例对象,持续复用它

·节省内存

·节省创建对象的开销

class StrTools:
    pass

str_tools = StrTools()
from test import str_tools

s1 = str_tools
s2 = str_tools
print(s1)
print(s2)

(2)工厂模式

将对象的创建由使用原生类本身创建,转换到由特定的工厂方法来创建

好处:

·大批量创建对象的时候有统一的入口,易于代码维护

·当发生修改,仅修改工厂类的创建方法即可

·符合现实世界的模式,即由工厂来制作产品(对象)

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')
student = factory.get_person('s')
teacher = factory.get_person('t')

4、多线程并执行

(1)进程

程序在操作系统内运行,即成为一个运行进程

(2)线程

是进程的实际工作最小单位,进程内部可以有多个线程,程序的运行本质就是由进程内部的线程在实际工作的

(3)并行执行

·多个进程同时在运行,即不同的程序同时运行,称之为:多任务并行执行

·一个进程内的多个线程同时在运行,称之为:多线程并行执行

5、多线程编程

threading模块实现多线程

thread_obj =threading.Thread(target=func) 创建线程对象

thread_obj.start()启动线程执行

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


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

if __name__ == '__main__':
    sing()
    dance()
# Singing...
# Singing...
# Singing...
# Singing...
# .....

则使用多线程后:

import threading
import time


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

if __name__ == '__main__':
    sing_thread = threading.Thread(target=sing)
    dance_thread = threading.Thread(target=dance)
    sing_thread.start()
    dance_thread.start()

需要传参:

·args参数以元组的方式给执行任务传参

或kwargs参数以字典的方式给执行任务传参

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=("Singing...",))
    dance_thread = threading.Thread(target=dance, kwargs={ "msg": "Dancing..."})
    sing_thread.start()
    dance_thread.start()

6、Socket服务端开发

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

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

主要步骤:

(1)创建socket对象

(2)绑定socket_server到指定IP和地址

(3)服务端开始监听端口

(4)接收客户端连接,获得连接对象

(5)客户端连接后,通过recv方法,接收客户端发送的消息

(6)通过conn(客户端当次连接对象),调用send方法可回复消息

(7)conn(客户端当次连接对象)和socket_server对象调用close方法,关闭连接

import socket
# 创建Socket对象
socket_server = socket.socket()

# 绑定IP地址和端口
socket_server.bind(("localhost", 8888))

#监听端口,listen()接受一个整数传参数,表示接受的链接数量
socket_server.listen(1)
# result: tuple = socket_server.accept()
# conn = result[0]
# address = result[1]

conn, address = socket_server.accept()
# accept返回的是二元元组(链接对象,客户端地址信息)
# 且是阻塞的方法,等待客户端的链接,若没有链接,就卡在这不执行了

print(f"接受客户端链接,客户端信息:{address}")

# recv返回值是一个字节数组,不是字符串,可以通过decode将字节数组转换为字符串
data: str = conn.recv(1024).decode("UTF-8")
# 接受客户信息,使用客户端和服务端的本次链接对象
print(f"客户端发来的消息是:{data}")

msg = input("请输入与客户端回复信息:").encode("UTF-8")
# encode将字符串转换为字节数组

conn.send(msg)
conn.close()
socket_server.close()

持续的消息:

import socket

socket_server = socket.socket()
socket_server.bind(("localhost", 8888))
#监听端口,listen()接受一个整数传参数,表示接受的链接数量
socket_server.listen(1)
# result: tuple = socket_server.accept()
# conn = result[0]
# address = result[1]
conn, address = socket_server.accept()
# accept返回的是二元元组(链接对象,客户端地址信息)
# 且是阻塞的方法,等待客户端的链接,若没有链接,就卡在这不执行了

print(f"接受客户端链接,客户端信息:{address}")


while True:
    # recv返回值是一个字节数组,不是字符串,可以通过decode将字节数组转换为字符串
    data: str = conn.recv(1024).decode("UTF-8")
    # 接受客户信息,使用客户端和服务端的本次链接对象
    print(f"客户端发来的消息是:{data}")

    msg = input("请输入与客户端回复信息:")
    # encode将字符串转换为字节数组
    if msg =='exit':
        break
    conn.send(msg.encode("UTF-8"))

conn.close()
socket_server.close()

7、Socket客户端开发

主要步骤:

(1)创建socket对象

(2)连接到服务器

(3)发送消息

(4)接收返回消息

(5)关闭链接

import socket
# 创建socket对象
socket_client = socket.socket()
# 连接服务器
socket_client.connect(("localhost", 8888))
# 发消息
socket_client.send("hello".encode("UTF_8"))
# 接收消息
recv_data = socket_client.recv(1024)
print(f"服务端回复消息:{recv_data.decode('UTF_8')}")
socket_client.close()

   持续消息:

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)
    print(f"服务端回复消息:{recv_data.decode('UTF_8')}")
socket_client.close()

先运行服务器端,再运行客户端:

主动客户端,被动服务器。

很高兴为您提供 Python 第十一章上机实践。本章的实践内容主要是关于文件处理、异常处理和模块的使用。 1. 文件处理 第一道题目是要求读取一个文件并统计其中单词的数量。您可以按照以下步骤完成任务: (1)使用 open() 函数打开文件。 (2)使用 read() 函数读取文件内容。 (3)使用 split() 函数将文件内容按照空格分割成单词。 (4)使用 len() 函数统计单词数量。 下面是一个示例代码: ```python with open('file.txt', 'r') as f: content = f.read() words = content.split(' ') count = len(words) print(f'The file has {count} words.') ``` 2. 异常处理 第二道题目是要求编写一个函数,将两个数相除并返回结果。但如果除数为 0,则应该抛出一个 ZeroDivisionError 异常。您可以按照以下步骤完成任务: (1)定义一个函数。 (2)使用 if 语句判断除数是否为 0。 (3)如果除数为 0,则使用 raise 语句抛出一个 ZeroDivisionError 异常。 (4)如果除数不为 0,则返回两个数的商。 下面是一个示例代码: ```python def divide(num1, num2): if num2 == 0: raise ZeroDivisionError('division by zero') else: return num1 / num2 try: result = divide(10, 0) except ZeroDivisionError as e: print(e) ``` 3. 模块的使用 第三道题目是要求使用 Python 标准库中的 random 模块生成一个随机数。您可以按照以下步骤完成任务: (1)使用 import 语句导入 random 模块。 (2)使用 random 模块中的 randint() 函数生成一个随机数。 下面是一个示例代码: ```python import random num = random.randint(1, 100) print(f'The random number is {num}.') ``` 希望这些实践题可以帮助您更好地理解 Python 文件处理、异常处理和模块的使用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值