在python中使用装饰器设置全局变量
Using decorators in python to set global variables
我正在尝试通过使用装饰器来减少 SLOC。我有一个案例需要启动四个 TCP 服务器并将连接的客户端保存为全局变量。这是代码。
# The sockets we will be using
socket0_client = None
socket1_client = None
socket2_client = None
socket3_client = None
# Populate them
def save_client(global_client_var):
def decorator(func):
async def inner(client, verbose=False):
global_client_var = client
# Receive stuff
with client:
while True:
# Get data. If there is no data, quit
data = await loop.sock_recv(client, 10000)
if not data:
break
# respond to the data
await func(client, data)
return inner
return decorator
@save_client(socket0_client)
async def socket0_reply(client, data):
await loop.sock_sendall(client, b'Got:'+data)
@save_client(socket1_client)
async def socket1_reply(client, data):
await loop.sock_sendall(client, b'Got:'+data)
@save_client(socket2_client)
async def socket2_reply(client, data):
await loop.sock_sendall(client, b'Got:'+data)
@save_client(socket3_client)
async def socket3_reply(client, data):
await loop.sock_sendall(client, b'Got:'+data)
loop.create_task(tcp_server.single_server(('', 60001), task=socket0_reply, verbose=True))
loop.create_task(tcp_server.single_server(('', 60002), task=socket1_reply, verbose=True))
loop.create_task(tcp_server.single_server(('', 60003), task=socket2_reply, verbose=True))
loop.create_task(tcp_server.single_server(('', 60004), task=socket3_reply, verbose=True))
有一个函数我没有代码。它是 single_server 函数。它绑定到给定地址的服务器,等待连接,然后在新连接的客户端上调用任务。
我遇到的问题是,尽管在内部函数中填充了客户端,并且明确设置为 global_client_var,但从未设置全局套接字。他们仍然 None。
这是怎么回事?如何设置这些全局变量?
您不能更新 Python 函数参数指向的引用,这是您的代码试图做的事情。 Python 中的所有函数调用参数均按值传递;但是,在这种情况下,您可以将项目附加到传入列表或字典中:
sockets = {}
# Populate them
def save_client(global_client_var):
def decorator(func):
async def inner(client, verbose=False):
sockets[global_client_var] = client
# Receive stuff
with client:
while True:
# Get data. If there is no data, quit
data = await loop.sock_recv(client, 10000)
if not data:
break
# respond to the data
await func(client, data)
return inner
return decorator
@save_client(0)
async def socket0_reply(client, data):
await loop.sock_sendall(client, b'Got:'+data)
@save_client(1)
async def socket1_reply(client, data):
await loop.sock_sendall(client, b'Got:'+data)
@save_client(2)
async def socket2_reply(client, data):
await loop.sock_sendall(client, b'Got:'+data)
@save_client(3)
async def socket3_reply(client, data):
await loop.sock_sendall(client, b'Got:'+data)
我正在尝试通过使用装饰器来减少 SLOC。我有一个案例需要启动四个 TCP 服务器并将连接的客户端保存为全局变量。这是代码。
# The sockets we will be using
socket0_client = None
socket1_client = None
socket2_client = None
socket3_client = None
# Populate them
def save_client(global_client_var):
def decorator(func):
async def inner(client, verbose=False):
global_client_var = client
# Receive stuff
with client:
while True:
# Get data. If there is no data, quit
data = await loop.sock_recv(client, 10000)
if not data:
break
# respond to the data
await func(client, data)
return inner
return decorator
@save_client(socket0_client)
async def socket0_reply(client, data):
await loop.sock_sendall(client, b'Got:'+data)
@save_client(socket1_client)
async def socket1_reply(client, data):
await loop.sock_sendall(client, b'Got:'+data)
@save_client(socket2_client)
async def socket2_reply(client, data):
await loop.sock_sendall(client, b'Got:'+data)
@save_client(socket3_client)
async def socket3_reply(client, data):
await loop.sock_sendall(client, b'Got:'+data)
loop.create_task(tcp_server.single_server(('', 60001), task=socket0_reply, verbose=True))
loop.create_task(tcp_server.single_server(('', 60002), task=socket1_reply, verbose=True))
loop.create_task(tcp_server.single_server(('', 60003), task=socket2_reply, verbose=True))
loop.create_task(tcp_server.single_server(('', 60004), task=socket3_reply, verbose=True))
有一个函数我没有代码。它是 single_server 函数。它绑定到给定地址的服务器,等待连接,然后在新连接的客户端上调用任务。
我遇到的问题是,尽管在内部函数中填充了客户端,并且明确设置为 global_client_var,但从未设置全局套接字。他们仍然 None。
这是怎么回事?如何设置这些全局变量?
您不能更新 Python 函数参数指向的引用,这是您的代码试图做的事情。 Python 中的所有函数调用参数均按值传递;但是,在这种情况下,您可以将项目附加到传入列表或字典中:
sockets = {}
# Populate them
def save_client(global_client_var):
def decorator(func):
async def inner(client, verbose=False):
sockets[global_client_var] = client
# Receive stuff
with client:
while True:
# Get data. If there is no data, quit
data = await loop.sock_recv(client, 10000)
if not data:
break
# respond to the data
await func(client, data)
return inner
return decorator
@save_client(0)
async def socket0_reply(client, data):
await loop.sock_sendall(client, b'Got:'+data)
@save_client(1)
async def socket1_reply(client, data):
await loop.sock_sendall(client, b'Got:'+data)
@save_client(2)
async def socket2_reply(client, data):
await loop.sock_sendall(client, b'Got:'+data)
@save_client(3)
async def socket3_reply(client, data):
await loop.sock_sendall(client, b'Got:'+data)