2015-05-27 14 views
8

Tôi đã xem How to use a context manager inside a decorator and how to pass an object created in decorator to decorated function cũng như python decorators with parameters và tôi đang cố gắng kết hợp cả hai .. nhưng tôi đang cố gắng xoay đầu.Làm cách nào để viết một trình trang trí để bọc một thứ gì đó trong trình quản lý ngữ cảnh, có tham số?

Tôi muốn sử dụng các công cụ func @wrap trang trí để làm điều này nếu có thể, như tôi biết nếu sẽ duy trì chuỗi tài liệu.

Những gì tôi muốn làm là thế này:

def pyro_opener(func,service,database,port,secret_key): 
    def wrapper(params): 
     with Pyro4.Proxy("PYRO:"+service+"@"+database+":"+port) as obj: 
      obj.set_secret_key(secret_key) 
      return obj.func(params) 
    return wrapper 


@pyro_opener(output_service, employee_db,port=9876,secret_key="h3llow0rld") 
def get_employee_names(salary): 
    return obj.return_employee_names(salary) # obj is clearly not in scope here 
               # but what else can I do? 


get_employee_names(25000) 

>>>> Bob, Jane, Mary 

Tôi không nghĩ rằng việc này theo cách này, phương pháp return_employee_names là vào dịch vụ ở đầu kia của kết nối. Tôi có nên trả lời cuộc gọi chức năng không? Nếu vậy làm thế nào để tôi vượt qua các params sau đó?

Trả lời

6

Bạn sẽ vượt qua đối tượng được gắn với with ... as đối với chức năng được bao bọc; hàm để chấp nhận đối số như vậy.

Điều này tương tự như cách thức các phương thức hoạt động; họ chỉ là chức năng với một cuộc tranh cãi đầu tiên thêm (self) thông qua vào:

def pyro_opener(service, database, port, secret_key): 
    def decorator(func): 
     @wraps(func) 
     def wrapper(*args, **kw): 
      with Pyro4.Proxy("PYRO:{}@{}:{}".format(service, database, port)) as obj: 
       obj.set_secret_key(secret_key) 
       return func(obj, *args, **kw) 
     return wrapper 
    retutrn decorator 

@pyro_opener(output_service, employee_db, port=9876, secret_key="h3llow0rld") 
def get_employee_names(obj, salary): 
    return obj.return_employee_names(salary) 

Lưu ý rằng tôi đã có thêm một chức năng lồng nhau trong pyro_opener() để làm cho nó một nhà máy trang trí thích hợp.

+0

Vì vậy, khi tôi gọi 'get_employee_names', tôi lấy thông số obj từ đâu? Ngoài ra, tôi nghĩ rằng bằng cách sử dụng '@ wraps' có nghĩa là tôi sẽ không cần thêm mức độ decoratoryness ...? – Pureferret

+0

@Pureferret: xem xét kỹ phiên bản 'get_employee_names()' của tôi; đối số 'obj' là * rõ ràng *. 'functools.wraps()' không liên quan gì đến các nhà máy trang trí, và mọi thứ với việc sao chép siêu dữ liệu từ hàm được bao bọc đến trình bao bọc, để cái sau trông giống như bản gốc hơn. –

+0

@martjinpieters ý tôi là, khi tôi muốn sử dụng 'get_employee_names' tôi cần cung cấp các tham số obj (chỉ cần dòng tôi cần cung cấp lương). Tôi không thể gọi là phương thức 'get_employee_names (???, 300000)' nhưng tôi phải đặt cái gì vào '???'? – Pureferret

Các vấn đề liên quan