2012-01-04 6 views
9

giả định sau định nghĩa lớp:Python: kiểm tra xem phương pháp là tĩnh

class A: 
    def f(self): 
    return 'this is f' 

    @staticmethod 
    def g(): 
    return 'this is g' 

a = A() 

Vậy f là một phương pháp thông thường và g là một phương pháp tĩnh.

Bây giờ, làm cách nào để kiểm tra xem các đối tượng funcion a.f và a.g có tĩnh hay không? Có một "isstatic" funcion trong Python?

Tôi phải biết điều này vì tôi có danh sách chứa nhiều đối tượng hàm (phương pháp) khác nhau và gọi chúng là tôi phải biết liệu chúng có phải là "tự" là tham số hay không.

Trả lời

1

Tôi sẽ có một mô-đun để giải quyết vấn đề này. Và đó là giải pháp Python2/3 tương thích. Và nó cho phép để kiểm tra với phương pháp được kế thừa từ lớp cha.

Thêm vào đó, mô-đun này cũng có thể kiểm tra:

  1. thuộc tính thường xuyên
  2. phương pháp phong cách sở hữu
  3. phương pháp thông thường
  4. staticmethod
  5. classmethod

Ví dụ:

class Base(object): 
    attribute = "attribute" 

    @property 
    def property_method(self): 
     return "property_method" 

    def regular_method(self): 
     return "regular_method" 

    @staticmethod 
    def static_method(): 
     return "static_method" 

    @classmethod 
    def class_method(cls): 
     return "class_method" 

class MyClass(Base): 
    pass 

Đây là giải pháp cho staticmethod chỉ. Nhưng Tôi khuyên bạn nên sử dụng mô-đunposted here.

import inspect 

def is_static_method(klass, attr, value=None): 
    """Test if a value of a class is static method. 

    example:: 

     class MyClass(object): 
      @staticmethod 
      def method(): 
       ... 

    :param klass: the class 
    :param attr: attribute name 
    :param value: attribute value 
    """ 
    if value is None: 
     value = getattr(klass, attr) 
    assert getattr(klass, attr) == value 

    for cls in inspect.getmro(klass): 
     if inspect.isroutine(value): 
      if attr in cls.__dict__: 
       binded_value = cls.__dict__[attr] 
       if isinstance(binded_value, staticmethod): 
        return True 
    return False 
14

Cho phép thử nghiệm một chút:

>>> import types 
>>> class A: 
... def f(self): 
...  return 'this is f' 
... @staticmethod 
... def g(): 
...  return 'this is g' 
... 
>>> a = A() 
>>> a.f 
<bound method A.f of <__main__.A instance at 0x800f21320>> 
>>> a.g 
<function g at 0x800eb28c0> 
>>> isinstance(a.g, types.FunctionType) 
True 
>>> isinstance(a.f, types.FunctionType) 
False 

Vì vậy, có vẻ như bạn có thể sử dụng types.FunctionType để phân biệt phương pháp tĩnh.

+0

cảm ơn bạn đã chỉ cho tôi mô-đun "loại", tôi gần như quên nó. –

4

Tại sao phải bận tâm? Bạn chỉ có thể gọi g như bạn gọi f:

a = A() 
a.f() 
a.g() 
+0

wow, quả thật vậy, bạn đã đúng! Tôi nghĩ rằng nó sẽ không hoạt động vì tôi có các phương thức trong một danh sách, nói 'l = [a.f, a.g]', và gọi chúng bằng 'l [0]()' và 'l [1]()'. Nhưng nó đã có tác dụng! Lạ lùng, tôi luôn nghĩ rằng các phương thức thông thường cần tham chiếu đến đối tượng chứa của chúng như tham số đầu tiên. Tôi có nghĩa là, nếu tôi làm 'A.f()', nó là một lỗi, trong khi 'A.g()' hoạt động, trong khi 'A.f (a)' cũng hoạt động tốt. –

+0

Một trong nhiều lý do tại sao Python rất dễ sử dụng :) – rzetterberg

+1

Đây rõ ràng là câu trả lời hay (đừng kiểm tra xem phương thức có tĩnh không!) cho vấn đề, nhưng nó không trả lời câu hỏi trong tiêu đề (kiểm tra nếu phương thức là tĩnh). – Jiri

12

cách tiếp cận của bạn có vẻ hơi thiếu sót đối với tôi, nhưng bạn có thể kiểm tra lớp thuộc tính:

(bằng Python 2.7):

>>> type(A.f) 
<type 'instancemethod'> 
>>> type(A.g) 
<type 'function'> 

hoặc các thuộc tính mẫu trong Python 3.x

>>> a = A() 
>>> type(a.f) 
<type 'method'> 
>>> type(a.g) 
<type 'function'> 
+1

Lưu ý rằng điều này chỉ hoạt động nếu đối tượng được khởi tạo (ít nhất là trong python 3), vì vậy nếu bạn muốn kiểm tra xem một phương thức là tĩnh mà không instantiating đối tượng, sau đó điều này sẽ không hoạt động. – DuckPuncher

+0

@DuckPuncher Cảm ơn! Bạn đã sửa, tôi đã cập nhật câu trả lời. – Jiri