2013-07-08 27 views
5

Tôi muốn sử dụng một trình trang trí chấp nhận một đối số, kiểm tra xem đối số đó có phải là Không, và nếu True cho phép chức năng trang trí chạy.Làm thế nào để chuyển một biến lớp tới một trình trang trí bên trong định nghĩa lớp?

Tôi muốn sử dụng trình trang trí này bên trong định nghĩa lớp, bởi vì tôi có một tập hợp các phương thức lớp bắt đầu bằng việc kiểm tra xem một biến lớp cụ thể có Không hay không. Tôi nghĩ rằng nó sẽ đẹp hơn nếu tôi sử dụng một trang trí.

Tôi muốn làm điều gì đó như thế này:

# decorator 
def variable_tester(arg): 
    def wrap(f): 
     def wrapped_f(*args): 
      if arg is not None: 
       f(*args) 
      else: 
       pass 
     return wrapped_f 
    return wrap 

# class definition 
class my_class(object): 
    def __init__(self): 
     self.var = None 

    @variable_tester(self.var) # This is wrong. How to pass self.var to decorator? 
    def printout(self): 
     print self.var 

    def setvar(self, v): 
     self.var = v 

# testing code 
my_instance = my_class() 
my_instance.printout() # It should print nothing 

my_instance.setvar('foobar') 
my_instance.printout() # It should print foobar 

Trả lời

5

Đây là một chút khó khăn, bởi vì bạn muốn làm một vài điều, mỗi người trong số họ một chút khó tính: (1) Bạn muốn vượt qua một đối số cho một trang trí và (2) bạn muốn đối số đó tham chiếu đến cá thể, nhưng cá thể không tồn tại tại thời điểm trang trí, vì vậy chúng ta sẽ phải trì hoãn nó bằng cách nào đó. Bạn có thể sử dụng hàm hoặc itemgetter, nhưng ở đây tôi sẽ sử dụng một chuỗi và tôi sẽ không sử dụng functools.wraps như tôi nên vì tôi lười.

Cái gì như:

# really, it's variable-tester-factory 
def variable_tester(target): 
    def deco(function): 
     def inner(self, *args, **kwargs): 
      if getattr(self, target) is not None: 
       return function(self, *args, **kwargs) 
     return inner 
    return deco 

class my_class(object): 
    def __init__(self): 
     self.var = None 

    @variable_tester('var') 
    def printout(self): 
     print self.var 

nên làm việc:

>>> a = my_class() 
>>> print a.var 
None 
>>> a.printout() 
>>> a.var = 'apple' 
>>> a.printout() 
apple 
+1

"hoặc một 'itemgetter'": ​​hoặc thậm chí một [ 'attrgetter'] (http://docs.python.org/ 2/library/operator.html # operator.attrgetter) - sự tồn tại mà tôi không biết đến cho đến bây giờ. – glglgl

+0

@glglgl: điểm tốt, bằng cách đó bạn sẽ không phải thêm '__getitem__'. – DSM

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