2016-11-23 17 views
5

Tôi đang cố gắng trang trí tất cả các phương thức trong lớp và tôi đã có được mã này, nhưng tôi cũng đang cố gắng ghi nhật ký các cuộc gọi tới các toán tử như * + - /, có cách nào để trang trí chúng hay không. để đăng nhập các cuộc gọi?Các toán tử trang trí python3.5


class Logger(object): 
    def __init__(self, bool): 
     self.bool = bool 

    def __call__(self, cls): 
     class DecoratedClass(cls): 
      def __init__(cls, *args, **kwargs): 
       super().__init__(*args, **kwargs) 

       if not(self.bool): 
        return 
       methods = [func for func in dir(cls) 
         if callable(getattr(cls, func)) 
         and not func.startswith("__class")] 
       for func in methods: 
        old_func = getattr(cls, func) 
        def decorated_function(fname, fn): 
         def loggedFunction(*args, **kwargs): 
          print("Calling {0} from {3} with params {1} and kwargs {2}".format(fname.upper(), args, kwargs, cls)) 
          return fn(*args, **kwargs) 
         return loggedFunction 
        setattr(cls, func, decorated_function(func, old_func)) 

     return DecoratedClass 

@Logger(True) 
class DummyClass(): 
    def __init__(self,foo): 
     self.foo = foo 
    def bar(self): 
     print(self.foo) 
    def __mul__(self,other): 
     print("Hello",other) 
if __name__ == '__main__': 
    a = DummyClass('hola') 
    a.method() 
    a.__mul__(a) #this is logged 
    print(a*a) #this is not logged by decorator 

Trả lời

2

Nhờ Łukasz, đây là một tập lệnh làm việc.

Khó khăn tôi gặp phải là xử lý nhiều phiên bản và tránh trang trí nhiều lần cùng một phương pháp lớp. Để xử lý vấn đề này, tôi theo dõi các phương pháp lớp trang trí (cls.__logged).

Một khó khăn khác là để đối phó với các phương pháp kỳ diệu như __setattr__, __getattribute__, __repr__ ... Giải pháp của tôi là để bỏ qua chúng, ngoại trừ một danh sách mà bạn phải xác định lúc khởi động (loggable_magic_methods).

from functools import wraps 


loggable_magic_methods = ['__mul__',] 


def is_magic_method(method): 
    return method.startswith('__') 


class Logger(object): 
    def __init__(self, bool): 
     self.bool = bool 

    def __call__(self, cls): 

     class LoggedClass(cls): 
      cls.__logged = [] 
      def __init__(instance, *args, **kwargs): 
       super().__init__(*args, **kwargs) 

       if not(self.bool): 
        return 

       methods = [funcname for funcname in dir(instance) 
          if callable(getattr(instance, funcname)) 
          and (funcname in loggable_magic_methods or not is_magic_method(funcname))] 

       def logged(method): 
        @wraps(method) 
        def wrapper(*args, **kwargs): 
         print (method.__name__, args, kwargs, cls) 
         return method(*args, **kwargs) 
        return wrapper 

       for funcname in methods: 
        if funcname in cls.__logged: 
         continue 

        if is_magic_method(funcname): 
         setattr(cls, funcname, logged(getattr(cls, funcname))) 
         cls.__logged.append(funcname) 
        else: 
         setattr(instance, funcname, logged(getattr(instance, funcname))) 
     return LoggedClass 

@Logger(True) 
class DummyClass(): 
    def __init__(self, foo, coef): 
     self.foo = foo 
     self.coef = coef 
    def bar(self): 
     print(self.foo) 
    def __mul__(self, other): 
     print(self.foo) 
     print(other.foo) 
     return self.coef * other.coef 

if __name__ == '__main__': 
    a = DummyClass('hola', 1) 
    a.bar() 
    print() 
    print(a.__mul__(a)) 
    print() 
    print(a*a) 
    print() 
    b = DummyClass('gracias', 2) 
    b.bar() 
    print() 
    print(b.__mul__(a)) 
    print() 
    print(b*a) 
2

giá trị Hiện nay bạn đang vá trên ví dụ. Việc bạn sử dụng số cls trong số __init__ là chữ ký của bạn bè - thực ra đây là chữ thường cũ self trong trường hợp này.

Nếu bạn muốn ghi đè các phương pháp ma thuật, thông dịch viên sẽ tìm kiếm chúng trên các đối tượng lớp học, không phải trên trường hợp.

dụ tối thiểu:

class DummyClass: 
    def __init__(self, foo): 
     self.foo = foo 
    def __mul__(self, other): 
     return self.foo * other.foo 


def logged(method): 
    def wrapper(*args, **kwargs): 
     print (method.__name__, args, kwargs) 
     return method(*args, **kwargs) 
    return wrapper 

DummyClass.__mul__ = logged(DummyClass.__mul__) 


a = DummyClass(1) 
b = DummyClass(2) 
assert a * a == 1 
assert a * b == 2 
assert b * b == 4 

Mỗi cuộc gọi được ghi lại.

>>> a = DummyClass(1) 
>>> b = DummyClass(2) 
>>> assert a * a == 1 
__mul__ (<__main__.DummyClass object at 0x00000000011BFEB8>, <__main__.DummyClass object at 0x00000000011BFEB8>) {} 
>>> assert a * b == 2 
__mul__ (<__main__.DummyClass object at 0x00000000011BFEB8>, <__main__.DummyClass object at 0x00000000011BF080>) {} 
>>> assert b * b == 4 
__mul__ (<__main__.DummyClass object at 0x00000000011BF080>, <__main__.DummyClass object at 0x00000000011BF080>) {} 

Tôi sẽ để lại nhiệm vụ viết lại cách tiếp cận vá lỗi cho bạn.

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