2009-03-25 30 views
10

Tôi có một chương trình python với 2 luồng (hãy đặt tên cho chúng là 'nguồn' và 'đích'). Chuỗi nguồn đôi khi đăng thông báo đến đích luồng với một số đối số. So với chủ đề đích chọn một tin nhắn, nó phải gọi một hàm tương ứng với các di tích được lưu trong tin nhắn.cách đặt hàm và đối số vào hàng đợi python?

Nhiệm vụ này có thể được giải quyết theo nhiều cách. Một cách dễ dàng là tu đặt một lớn 'nếu ... if..if' trong chu trình chọn thư của chuỗi đích và gọi hàm theo kiểu thông báo nhận được và đối số đã lưu. Nhưng điều này sẽ dẫn đến amounf lớn của mã (hoặc bảng tra cứu lớn) và thêm tin nhắn/chức năng xử lý mới sẽ phát triển bước bổ sung để viết mã trong chu kỳ chọn tin nhắn.

Kể từ khi xử lý trăn chức năng như các đối tượng hạng nhất và có tuples, tôi muốn để đặt một chức năng và argumens bên trong một thông điệp, vì vậy so với chủ đề đến nhặt nhắn nó chỉ cần gọi một functon lưu trong moto tin nhắn mà không cần bất kỳ kiến thức chức năng của nó là gì.

tôi có thể viết một mã cho một chức năng với số lượng nhất định đối số:

from Queue import * 
from thread import * 
from time import * 

q = Queue() 

def HandleMsg(arg1, arg2) : 
    print arg1, arg2 

def HandleAnotherMsg(arg1, arg2, arg3) : 
    print arg1, arg2, arg3 

def DestinationThread(a) : 
    while True : 
    (f, a, b) = q.get() 
    f(a, b) 

start_new_thread(DestinationThread, (0,)) 
print "start" 
sleep(1) 
q.put((HandleMsg, 1, 2)) 
sleep(1) 
print "stop" 

Câu hỏi đặt ra là: làm thế nào để sửa đổi một mã số vì vậy tôi có thể đặt() một hàm với bất kỳ số lượng các đối số trong hàng đợi ? ví dụ HandleAnotherMsg()? Sử dụng q.put ((HandleAnotherMsg, 1, 2, 3)) sẽ tăng lên một lỗi biên dịch :(

+0

Bạn có thể đăng lỗi bạn đang nhận được không? –

Trả lời

24

Vì vậy, đơn giản:

def DestinationThread(a) : 
    while True : 
    items = q.get() 
    func = items[0] 
    args = items[1:] 
    func(*args) 
-2

Tại sao bạn không phân lớp Queue?


class MyQueue(Queue): 
    # by using *args, you can have a variable number of arguments 
    def put(self,*args): 
    for arg in args: 
     Queue.put(self,arg) 

hay, tại sao bạn không đặt một danh sách


list = [function_obj] 
for arg in function_args: 
    list.append(arg) 
queue.put(list) 
+0

Có ai muốn ý tưởng này được đăng tại sao không? –

+0

Nó không trả lời câu hỏi. Mỗi mục trong hàng đợi cần phải mã hóa một hàm và một số đối số không xác định. Đẩy mỗi đối số dưới dạng giá trị riêng biệt trên hàng đợi không hữu ích. – cthulahoops

+0

Thực ra, đoạn mã thứ hai là có liên quan - những đoạn mã trên có ích hơn. – cthulahoops

8
from Queue import * 
from thread import * 
from time import * 

q = Queue() 

def HandleMsg(arg1, arg2) : 
    print arg1, arg2 

def HandleAnotherMsg(arg1, arg2, arg3) : 
    print arg1, arg2, arg3 

def DestinationThread() : 
    while True : 
    f, args = q.get() 
    f(*args) 

start_new_thread(DestinationThread, tuple()) 
print "start" 
sleep(1) 
q.put((HandleMsg, [1, 2])) 
sleep(1) 
q.put((HandleAnotherMsg, [1, 2, 3])) 
sleep(1) 
print "stop" 
0

Có vẻ như bạn muốn sử dụng apply() nội tại hoặc người thừa kế của nó:

def f(x. y): 
    print x+y 

args = (1, 2) 

apply(f, args) # old way 

f(*args)  # new way 
2

Tôi đã sử dụng một cấu trúc tương tự như trước đây:

class Call: 
    def __init__(self, fn, *args, **kwargs): 
     self.fn = fn 
     self.args = args 
     self.kwargs = kwargs 

    def __call__(self): 
     return self.fn(*self.args, **self.kwargs) 


x = Call(zip, [0,1], [2,3], [4,5]) 

Sau đó, bạn sẽ có thể vượt qua x vào chủ đề khác của bạn và gọi nó từ đó:

x() # returns the same as zip([0,1], [2,3], [4,5]) 
0

Bạn có thể tạo một lớp thông báo trừu tượng với phương thức chạy. Sau đó, cho mỗi chức năng cần được truyền qua hàng đợi, phân lớp và thực hiện chức năng như phương thức chạy. Chuỗi gửi sẽ tạo một thể hiện của lớp con phù hợp và đặt nó vào hàng đợi. Chuỗi nhận sẽ nhận được một đối tượng từ hàng đợi và thực thi một cách mù quáng phương thức chạy.

Điều này thường được gọi là mẫu Lệnh (Gamma et al.)

Ví dụ:

class Message (object): 
    """abstract message class""" 
    def __init__(self, **kwargs): 
     self.kwargs = kwargs 

    def run(self): 
     pass 


class MessageOne (Message): 
    """one message class""" 
    def run(self): 
     # perform this emssage's action using the kwargs 

Người gửi sẽ nhanh chóng và gửi tin nhắn:

queue.put(MessageOne(one='Eins', two='Deux')) 

Người nhận chỉ đơn giản là được một đối tượng tin nhắn và thực hiện nó chạy phương pháp (mà không cần phải it..else .. thông qua các loại tin nhắn có sẵn):

msg = queue.get() 
msg.run() 
11

Một tùy chọn thú vị khác là đơn giản y để vượt qua trong một lambda.

q.put(lambda: HandleMsg(1,2)) 
q.put(lambda: HandleAnother(8, "hello", extra="foo")) 

def DestinationThread() : 
    while True : 
     f = q.get() 
     f() 
Các vấn đề liên quan