【问题标题】:How do I check the methods that an object has, in Python?如何在 Python 中检查对象具有的方法?
【发布时间】:2010-12-26 06:13:24
【问题描述】:

例如,一个列表。

l1 = [1, 5, 7] 如何检查它具有的方法?

(例如l1.append)

或者一个字符串... 字符串.lower(

【问题讨论】:

    标签: python object methods


    【解决方案1】:

    您可以使用dir 获取任何对象的方法列表。这在交互式提示中非常有用:

    >>> dir(l1)
    ['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__delslice__', '__doc__', '__eq__',
    '__ge__', '__getattribute__', '__getitem__', '__getslice__', '__gt__', '__hash__', '__iadd__', '__imul__',
    '__init__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__',
    '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__setslice__',
    '__str__', 'append', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']
    

    有趣的方法通常是那些不以下划线开头的方法。如果您愿意,您可以编写自己的 dir 版本,忽略以下划线开头的名称:

    >>> mydir = lambda a:[x for x in dir(a) if not x.startswith('_')]
    >>> mydir([])
    ['append', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']
    

    【讨论】:

    • 至少你应该使用if not (x.startswith('__') and x.endswith('__')),因为人们经常使用__前缀来表示私有成员。您只想删除以 __ 开头和结尾的那些
    • 我只是在这里猜测,但我认为 alex 想知道 public 界面中可用的内容。
    • 可能值得指出的是,dir() 不仅限于交互式提示(您的声明可以这样被不熟悉的人阅读)
    • 我已经改写了它以避免混淆。感谢您的评论。
    • @Mark Byers:那么在这种情况下,您还想过滤以_ 开头的内容。无论如何......这只是一个挑剔的:-)。你的回答在我的书中仍然很好,并且明白了:-)。
    【解决方案2】:

    您可能想查看inspect 模块中的getmembers 函数

    In [1]: import inspect
    
    In [2]: inspect?
    Type:       module
    Base Class: <type 'module'>
    String Form:    <module 'inspect' from '/usr/lib/python2.6/inspect.pyc'>
    Namespace:  Interactive
    File:       /usr/lib/python2.6/inspect.py
    Docstring:
        Get useful information from live Python objects.
    
        This module encapsulates the interface provided by the internal special
        attributes (func_*, co_*, im_*, tb_*, etc.) in a friendlier fashion.
        It also provides some help for examining source code and class layout.
    
        Here are some of the useful functions provided by this module:
    
            ismodule(), isclass(), ismethod(), isfunction(), isgeneratorfunction(),
                isgenerator(), istraceback(), isframe(), iscode(), isbuiltin(),
                isroutine() - check object types
            getmembers() - get members of an object that satisfy a given condition
    
            getfile(), getsourcefile(), getsource() - find an object's source code
            getdoc(), getcomments() - get documentation on an object
            getmodule() - determine the module that an object came from
            getclasstree() - arrange classes so as to represent their hierarchy
    
            getargspec(), getargvalues() - get info about function arguments
            formatargspec(), formatargvalues() - format an argument spec
            getouterframes(), getinnerframes() - get info about frames
            currentframe() - get the current stack frame
            stack(), trace() - get info about frames on the stack or in a traceback
    
    In [3]: l1=[1,5,7]
    
    In [4]: inspect.getmembers(l1)
    Out[4]: 
    [('__add__', <method-wrapper '__add__' of list object at 0xa38716c>),
     ('__class__', <type 'list'>),
     ('__contains__', <method-wrapper '__contains__' of list object at 0xa38716c>),
     ('__delattr__', <method-wrapper '__delattr__' of list object at 0xa38716c>),
     ('__delitem__', <method-wrapper '__delitem__' of list object at 0xa38716c>),
     ('__delslice__', <method-wrapper '__delslice__' of list object at 0xa38716c>),
     ('__doc__',
      "list() -> new list\nlist(sequence) -> new list initialized from sequence's items"),
     ('__eq__', <method-wrapper '__eq__' of list object at 0xa38716c>),
     ('__format__', <built-in method __format__ of list object at 0xa38716c>),
     ('__ge__', <method-wrapper '__ge__' of list object at 0xa38716c>),
     ('__getattribute__',
      <method-wrapper '__getattribute__' of list object at 0xa38716c>),
     ('__getitem__', <built-in method __getitem__ of list object at 0xa38716c>),
     ('__getslice__', <method-wrapper '__getslice__' of list object at 0xa38716c>),
     ('__gt__', <method-wrapper '__gt__' of list object at 0xa38716c>),
     ('__hash__', None),
     ('__iadd__', <method-wrapper '__iadd__' of list object at 0xa38716c>),
     ('__imul__', <method-wrapper '__imul__' of list object at 0xa38716c>),
     ('__init__', <method-wrapper '__init__' of list object at 0xa38716c>),
     ('__iter__', <method-wrapper '__iter__' of list object at 0xa38716c>),
     ('__le__', <method-wrapper '__le__' of list object at 0xa38716c>),
     ('__len__', <method-wrapper '__len__' of list object at 0xa38716c>),
     ('__lt__', <method-wrapper '__lt__' of list object at 0xa38716c>),
     ('__mul__', <method-wrapper '__mul__' of list object at 0xa38716c>),
     ('__ne__', <method-wrapper '__ne__' of list object at 0xa38716c>),
     ('__new__', <built-in method __new__ of type object at 0x822be40>),
     ('__reduce__', <built-in method __reduce__ of list object at 0xa38716c>),
     ('__reduce_ex__',
      <built-in method __reduce_ex__ of list object at 0xa38716c>),
     ('__repr__', <method-wrapper '__repr__' of list object at 0xa38716c>),
     ('__reversed__', <built-in method __reversed__ of list object at 0xa38716c>),
     ('__rmul__', <method-wrapper '__rmul__' of list object at 0xa38716c>),
     ('__setattr__', <method-wrapper '__setattr__' of list object at 0xa38716c>),
     ('__setitem__', <method-wrapper '__setitem__' of list object at 0xa38716c>),
     ('__setslice__', <method-wrapper '__setslice__' of list object at 0xa38716c>),
     ('__sizeof__', <built-in method __sizeof__ of list object at 0xa38716c>),
     ('__str__', <method-wrapper '__str__' of list object at 0xa38716c>),
     ('__subclasshook__',
      <built-in method __subclasshook__ of type object at 0x822be40>),
     ('append', <built-in method append of list object at 0xa38716c>),
     ('count', <built-in method count of list object at 0xa38716c>),
     ('extend', <built-in method extend of list object at 0xa38716c>),
     ('index', <built-in method index of list object at 0xa38716c>),
     ('insert', <built-in method insert of list object at 0xa38716c>),
     ('pop', <built-in method pop of list object at 0xa38716c>),
     ('remove', <built-in method remove of list object at 0xa38716c>),
     ('reverse', <built-in method reverse of list object at 0xa38716c>),
     ('sort', <built-in method sort of list object at 0xa38716c>)]
    

    【讨论】:

      【解决方案3】:

      交互式 Python 有一个 help 函数,您可以使用任何东西:

      >>> help(list)
      Help on class list in module __builtin__:
      
      class list(object)
       |  list() -> new list
       |  list(sequence) -> new list initialized from sequence´s items
       |
       |  Methods defined here:
       |
       |  __add__(...)
       |      x.__add__(y) <==> x+y
       |
       |  __contains__(...)
       |      x.__contains__(y) <==> y in x
       |
       |  __delitem__(...)
       |      x.__delitem__(y) <==> del x[y]
       |
       |  __delslice__(...)
       |      x.__delslice__(i, j) <==> del x[i:j]
       |
       |      Use of negative indices is not supported.
       |
       |  __eq__(...)
       |      x.__eq__(y) <==> x==y
       |
       |  __ge__(...)
       |      x.__ge__(y) <==> x>=y
       |
       |  __getattribute__(...)
       |      x.__getattribute__('name') <==> x.name
       |
       |  __getitem__(...)
       |      x.__getitem__(y) <==> x[y]
       |
       |  __getslice__(...)
       |      x.__getslice__(i, j) <==> x[i:j]
       |
       |      Use of negative indices is not supported.
       |
       |  __gt__(...)
       |      x.__gt__(y) <==> x>y
       |
       |  __iadd__(...)
       |      x.__iadd__(y) <==> x+=y
       |
       |  __imul__(...)
       |      x.__imul__(y) <==> x*=y
       |
       |  __init__(...)
       |      x.__init__(...) initializes x; see x.__class__.__doc__ for signature
       |
       |  __iter__(...)
       |      x.__iter__() <==> iter(x)
       |
       |  __le__(...)
       |      x.__le__(y) <==> x<=y
       |
       |  __len__(...)
       |      x.__len__() <==> len(x)
       |
       |  __lt__(...)
       |      x.__lt__(y) <==> x<y
       |
       |  __mul__(...)
       |      x.__mul__(n) <==> x*n
       |
       |  __ne__(...)
       |      x.__ne__(y) <==> x!=y
       |
       |  __repr__(...)
       |      x.__repr__() <==> repr(x)
       |
       |  __reversed__(...)
       |      L.__reversed__() -- return a reverse iterator over the list
       |
       |  __rmul__(...)
       |      x.__rmul__(n) <==> n*x
       |
       |  __setitem__(...)
       |      x.__setitem__(i, y) <==> x[i]=y
       |
       |  __setslice__(...)
       |      x.__setslice__(i, j, y) <==> x[i:j]=y
       |
       |      Use  of negative indices is not supported.
       |
       |  __sizeof__(...)
       |      L.__sizeof__() -- size of L in memory, in bytes
       |
       |  append(...)
       |      L.append(object) -- append object to end
       |
       |  count(...)
       |      L.count(value) -> integer -- return number of occurrences of value
       |
       |  extend(...)
       |      L.extend(iterable) -- extend list by appending elements from the iterable
       |
       |  index(...)
       |      L.index(value, [start, [stop]]) -> integer -- return first index of value.
       |      Raises ValueError if the value is not present.
       |
       |  insert(...)
       |      L.insert(index, object) -- insert object before index
       |
       |  pop(...)
       |      L.pop([index]) -> item -- remove and return item at index (default last).
       |      Raises IndexError if list is empty or index is out of range.
       |
       |  remove(...)
       |      L.remove(value) -- remove first occurrence of value.
       |      Raises ValueError if the value is not present.
       |
       |  reverse(...)
       |      L.reverse() -- reverse *IN PLACE*
       |
       |  sort(...)
       |      L.sort(cmp=None, key=None, reverse=False) -- stable sort *IN PLACE*;
       |      cmp(x, y) -> -1, 0, 1
       |
       |  ----------------------------------------------------------------------
       |  Data and other attributes defined here:
       |
       |  __hash__ = None
       |
       |  __new__ = <built-in method __new__ of type object at 0x1E1CF100>
       |      T.__new__(S, ...) -> a new object with type S, a subtype of T
      

      【讨论】:

        【解决方案4】:

        事实上,列表实例的所有成员都是方法。如果不是这样,你可以使用这个:

        l1 = [1, 5 , 7]
        print [name for name in dir(l1) if type(getattr(l1, name) == type(l1.append))]
        

        这将排除不是方法的成员。

        【讨论】:

        • if callable(getattr(l1, name))
        【解决方案5】:

        如果你安装IPython,那么你可以这样做:

        % ipython
        Python 2.6.4 (r264:75706, Nov  2 2009, 14:38:03) 
        Type "copyright", "credits" or "license" for more information.
        
        IPython 0.10 -- An enhanced Interactive Python.
        ?         -> Introduction and overview of IPython's features.
        %quickref -> Quick reference.
        help      -> Python's own help system.
        object?   -> Details about 'object'. ?object also works, ?? prints more.
        
        In [1]: l1=[1,5,7]
        
        In [2]: l1.
        l1.__add__           l1.__getslice__      l1.__new__           l1.append
        l1.__class__         l1.__gt__            l1.__reduce__        l1.count
        l1.__contains__      l1.__hash__          l1.__reduce_ex__     l1.extend
        l1.__delattr__       l1.__iadd__          l1.__repr__          l1.index
        l1.__delitem__       l1.__imul__          l1.__reversed__      l1.insert
        l1.__delslice__      l1.__init__          l1.__rmul__          l1.pop
        l1.__doc__           l1.__iter__          l1.__setattr__       l1.remove
        l1.__eq__            l1.__le__            l1.__setitem__       l1.reverse
        l1.__format__        l1.__len__           l1.__setslice__      l1.sort
        l1.__ge__            l1.__lt__            l1.__sizeof__        
        l1.__getattribute__  l1.__mul__           l1.__str__           
        l1.__getitem__       l1.__ne__            l1.__subclasshook__  
        
        In [2]: l1.
        

        在最后一行,键入对象名称、句点,然后按 TAB。 IPython 然后列出对象的所有属性。

        我发现 IPython 是探索对象属性的宝贵工具。它比标准的 Python 交互式提示使用起来要方便得多。除了其他漂亮的东西之外,在对象后面加上问号会得到它的文档字符串:

        In [6]: d.update?
        Type:       builtin_function_or_method
        Base Class: <type 'builtin_function_or_method'>
        String Form:    <built-in method update of dict object at 0xa3c024c>
        Namespace:  Interactive
        Docstring:
            D.update(E, **F) -> None.  Update D from dict/iterable E and F.
            If E has a .keys() method, does:     for k in E: D[k] = E[k]
            If E lacks .keys() method, does:     for (k, v) in E: D[k] = v
            In either case, this is followed by: for k in F: D[k] = F[k]
        

        并且,如果可用,两个问号会为您提供其源代码:

        In [18]: np.sum??
        Type:       function
        Base Class: <type 'function'>
        String Form:    <function sum at 0x9c501ec>
        Namespace:  Interactive
        File:       /usr/lib/python2.6/dist-packages/numpy/core/fromnumeric.py
        Definition: np.sum(a, axis=None, dtype=None, out=None)
        Source:
        def sum(a, axis=None, dtype=None, out=None):
        ...
            if isinstance(a, _gentype):
                res = _sum_(a)
                if out is not None:
                    out[...] = res
                    return out
                return res
            try:
                sum = a.sum
            except AttributeError:
                return _wrapit(a, 'sum', axis, dtype, out)
            return sum(axis, dtype, out)
        

        【讨论】:

          【解决方案6】:

          如果对象(通常可能是一个模块)有许多方法或属性,使用 dir 或 ipython 的 TAB 补全可能会变得复杂而难以跟踪。

          在这种情况下,我会使用如下示例中的过滤器:

          filter(lambda s: 'sin' in s.lower(), dir(numpy))
          

          导致

          ['arcsin',
           'arcsinh',
           'csingle',
           'isinf',
           'isposinf',
           'sin',
           'sinc',
           'single',
           'singlecomplex',
           'sinh']
          

          我发现探索未知对象非常方便,我希望它们必须有一个方法(或属性),该方法(或属性)应该作为其名称的一部分。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2010-09-07
            • 1970-01-01
            • 2016-05-12
            • 2011-07-04
            • 1970-01-01
            • 2011-06-07
            相关资源
            最近更新 更多