2010-01-01 16 views
25

Tại sao có thể decorator không trang trí một staticmethod hoặc một classmethod?Tại sao @decorator không thể trang trí một staticmethod hoặc một classmethod?

from decorator import decorator 

@decorator 
def print_function_name(function, *args): 
    print '%s was called.' % function.func_name 
    return function(*args) 

class My_class(object): 
    @print_function_name 
    @classmethod 
    def get_dir(cls): 
     return dir(cls) 

    @print_function_name 
    @staticmethod 
    def get_a(): 
     return 'a' 

Cả get_dirget_a kết quả trong AttributeError: <'classmethod' or 'staticmethod'>, object has no attribute '__name__'.

Tại sao phải dựa vào decorator trên thuộc tính __name__ thay vì thuộc tính func_name? (Afaik tất cả các hàm, bao gồm cả classmethods và staticmethods, có thuộc tính func_name.)

Chỉnh sửa: Tôi đang sử dụng Python 2.6.

+1

chức năng Tại sao các bạn gọi (* args) bên trong trang trí? Công việc của nó đơn giản là trả về một hàm (trong trường hợp của bạn, chưa sửa đổi). – gahooa

+4

gahooa: bởi vì đó là một cách 'trang trí' (những gì ông nhập khẩu, không phải là ngôn ngữ xây dựng) hoạt động, xem http://pypi.python.org/pypi/decorator. –

+0

@taldor bạn có mô-đun trang trí trong py 2.6? – mykhal

Trả lời

22

Nó hoạt động khi @classmathod@staticmethod là top-nhất trang trí:

from decorator import decorator 

@decorator 
def print_function_name(function, *args): 
    print '%s was called.' % function.func_name 
    return function(*args) 

class My_class(object): 
    @classmethod 
    @print_function_name 
    def get_dir(cls): 
     return dir(cls) 
    @staticmethod 
    @print_function_name 
    def get_a(): 
     return 'a' 
+7

Như một quy luật, 'classmethod' và 'staticmethod' áp dụng một loại ma thuật đặc biệt và phải được gọi là cuối cùng. –

3

Đây có phải là những gì bạn muốn không?

def print_function_name(function): 
    def wrapper(*args): 
     print('%s was called.' % function.__name__) 
     return function(*args) 
    return wrapper 

class My_class(object): 
    @classmethod 
    @print_function_name 
    def get_dir(cls): 
     return dir(cls) 

    @staticmethod 
    @print_function_name 
    def get_a(): 
     return 'a' 
+2

Tôi không chắc bạn đã nhận ra, nhưng gói "trang trí" mà anh ta đang sử dụng cũng giống như cấu trúc với "trình bao bọc". Sự khác biệt duy nhất giữa các đoạn mã của bạn là thứ tự áp dụng các trang trí trong My_class. Bạn có thể làm rõ rằng trong câu trả lời để giải thích tại sao nó sửa chữa mọi thứ. –

+0

Cảm ơn bạn đã sửa chữa. Tôi đã chơi với các vấn đề trong py3k, nơi mô-đun trang trí bị thiếu. Tôi có nghĩa là trả lời của tôi là nhanh chóng, và chắc chắn rằng ai đó sẽ đăng câu trả lời tốt hơn với giải thích chi tiết – mykhal

+0

@ (Peter Hansen) .. Tuy nhiên, không có mô-đun trang trí trong python 2.6 hoặc – mykhal

37

classmethodstaticmethod trở descriptor objects, không chức năng. Hầu hết các trang trí không được thiết kế để chấp nhận các bộ mô tả.

Thông thường, khi đó, bạn phải áp dụng classmethodstaticmethod cuối cùng khi sử dụng nhiều trang trí. Và kể từ khi trang trí được áp dụng theo thứ tự "dưới lên", classmethodstaticmethod thường là nguồn cấp cao nhất trong nguồn của bạn.

Như thế này:

class My_class(object): 
    @classmethod 
    @print_function_name 
    def get_dir(cls): 
     return dir(cls) 

    @staticmethod 
    @print_function_name 
    def get_a(): 
     return 'a' 
+7

+1 để thực sự trả lời câu hỏi ("tại sao ...?"). –

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