2016-12-06 36 views
0

我正試圖通過使用裝飾器來減少SLOC。我有一個案例,我需要啓動四個TCP服務器並將連接客戶端保存爲全局變量。這是代碼。在Python中使用裝飾器來設置全局變量

# 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,但全局套接字從不設置。他們仍然沒有。

這是怎麼回事?我怎樣才能得到這些全局變量?

+0

爲什麼不只是聲明'socket0_client'在功能全球'socket0_reply'然後將它們設置爲客戶端呢? – Skycc

+0

,因爲在從套接字接收數據之前,不會調用該代碼。我希望能夠在數據收到之前在別處使用套接字。 – jrk0414

回答

0

您無法更新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) 
+0

這似乎不適用於這種情況。在我將其設置爲客戶端之前添加'global global_client_var'這一行時,代碼中其他地方的值仍然爲'None'。 – jrk0414

+0

我誤讀了示例代碼。在Python中的函數調用中,所有參數都是按值傳遞的,不能用來更新變量綁定的引用;但是,您可以傳遞類似列表或字典的值,這些值可以附加到集合中。 – joemeilinger

+0

如果是字典,這會更好。問題是我需要知道哪個套接字屬於哪個,append方法不允許我跟蹤。 – jrk0414