【问题标题】:Looping over a Python / IronPython Object Methods循环 Python / IronPython 对象方法
【发布时间】:2010-10-30 01:30:57
【问题描述】:

循环遍历 Python 对象的方法并调用它们的正确方法是什么?

给定对象:

class SomeTest():
  def something1(self):
    print "something 1"
  def something2(self):
    print "something 2"

【问题讨论】:

  • 你为什么不使用 unittest 模块,它会为你做这件事?
  • 尝试学习 Python 内省/反射而不是单元测试。虽然我意识到这就是我正在尝试做的事情。

标签: python reflection ironpython introspection python-datamodel


【解决方案1】:

您可以使用检查模块来获取类(或实例)成员:

>>> class C(object):
...     a = 'blah'
...     def b(self):
...             pass
... 
...
>>> c = C()
>>> inspect.getmembers(c, inspect.ismethod)
[('b', <bound method C.b of <__main__.C object at 0x100498250>>)]

getmembers() 返回一个元组列表,其中每个元组是 (name, member)。 getmembers() 的第二个参数是谓词,它过滤返回列表(在这种情况下,只返回方法对象)

【讨论】:

    【解决方案2】:

    方法与函数和其他类型的可调用对象...

    (为了解决 Unknown 帖子中 cmets 中的问题。)

    首先,需要注意的是,除了用户定义的方法之外,还有内置的方法,而内置的方法,正如http://docs.python.org/reference/datamodel.html 的文档所说,“真的是一个不同的伪装内置函数”(它是一个 C 函数的包装器。)

    至于用户定义的方法,正如 Unknown 引用的引用所说:

    用户定义的方法对象结合 一个类,一个类实例(或无) 和任何可调用对象(通常是 用户自定义函数)。

    但这并不意味着“任何定义__call__ 并附加到对象的东西都是方法”。方法是可调用的,但可调用的不一定是方法。用户定义的方法是对引用内容的包装。

    希望这个输出(来自我方便的 Python 2.5.2)将显示区别:

    IDLE 1.2.2      
    >>> class A(object):
        x = 7
    
    
    >>> A  # show the class object
    <class '__main__.A'>
    >>> a = A()
    >>> a  # show the instance
    <__main__.A object at 0x021AFBF0>
    >>> def test_func(self):
        print self.x
    
    
    >>> type(test_func)  # what type is it?
    <type 'function'>
    >>> dir(test_func)  # what does it have?
    ['__call__', '__class__', '__delattr__', '__dict__', '__doc__', '__get__',
     '__getattribute__', '__hash__', '__init__', '__module__', '__name__',
     '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__',
     '__str__', 'func_closure', 'func_code', 'func_defaults', 'func_dict',
     'func_doc', 'func_globals', 'func_name']
    >>> # But now let's put test_func on the class...
    >>> A.test = test_func
    >>> type(A.test)  # What type does this show?
    <type 'instancemethod'>
    >>> dir(A.test)  # And what does it have?
    ['__call__', '__class__', '__cmp__', '__delattr__', '__doc__', '__get__',
     '__getattribute__', '__hash__', '__init__', '__new__', '__reduce__',
     '__reduce_ex__', '__repr__', '__setattr__', '__str__', 'im_class',
     'im_func', 'im_self']
    >>> # See, we just got a wrapper, and the function is in 'im_func'...
    >>> getattr(A.test, 'im_func')
    <function test_func at 0x0219F4B0>
    >>> # Now to show bound vs. unbound methods...
    >>> getattr(a.test, 'im_self') # Accessing it via the instance
    <__main__.A object at 0x021AFBF0>
    >>> # The instance is itself 'im_self'
    >>> a.test()
    7
    >>> getattr(A.test, 'im_self') # Accessing it via the class returns None...
    >>> print getattr(A.test, 'im_self')
    None
    >>> # It's unbound when accessed that way, so there's no instance in there
    >>> # Which is why the following fails...
    >>> A.test()
    
    Traceback (most recent call last):
      File "<pyshell#25>", line 1, in <module>
        A.test()
    TypeError: unbound method test_func() must be called with A instance as
    first argument (got nothing instead)
    >>>
    

    并且 - 编辑添加以下附加输出,这也是相关的......

    >>> class B(object):
        pass
    
    >>> b = B()
    >>> b.test = test_func  # Putting the function on the instance, not class
    >>> type(b.test)
    <type 'function'>
    >>> 
    

    我不会添加更多的输出,但是你也可以让一个类成为另一个类或实例的属性,而且,即使类是可调用的,你也不会得到一个方法。方法是使用非数据描述符实现的,因此如果您想了解有关它们如何工作的更多信息,请查找描述符。

    【讨论】:

    • 这是错误的原因。命题 1:用户定义的方法对象结合了一个类、一个类实例(或 None)和任何可调用对象。 (由 Python 手册定义) 命题 2:定义 call 的每个对象都是“可调用对象”。 (通过简单地定义调用,您可以像函数一样执行任何对象)。命题 3:因此,定义 call 并附加到对象的每个对象都是“用户定义的方法”。根据定义,“用户定义的方法”是一种方法。因此,当附加到对象时,您对“可调用不一定是方法”的引用是完全错误的。
    • 我还想指出,通常定义的方法和猴子修补方法之间显然存在区别。但是,这并不会使附加到对象的可调用对象是方法这一事实无效。它是否是特定类型并不重要。它是否绑定到特定实例并不重要。实际上,您所浪费的努力中的示例已经在您掩盖的手册中进行了描述,除了与您不同的是,它仍然将这些东西称为方法。再看一下链接,并阅读以开头的段落跨度>
    • (接上一条评论)“当通过检索创建用户定义的方法对象时”你就会明白我在说什么了。
    【解决方案3】:

    此代码 sn-p 将调用它在obj 中找到的任何内容并将结果存储在映射中,其中键是属性名称 — dict((k, v()) for (k, v) in obj.__dict__.iteritems() if k.startswith('something'))

    【讨论】:

      【解决方案4】:

      编辑

      丹尼尔,你错了。

      http://docs.python.org/reference/datamodel.html

      用户定义的方法

      用户定义的方法对象组合了一个类、一个类实例(或 无)和任何可调用对象(通常是用户定义的函数)。

      因此,任何定义 __call__ 并附加到对象的东西都是方法。

      回答

      查看对象有哪些元素的正确方法是使用 dir() 函数。

      显然这个例子只适用于不带参数的函数。

      a=SomeTest()
      for varname in dir(a):
          var = getattr(a, varname)
          if hasattr(var, "__call__"):
              var()
      

      【讨论】:

      • dir() 可能不是最好的方法,因为 dir() 不能保证 每个 成员,它只是说它会尝试获取“有趣”的。不过,这当然是一个开始。
      • 并非您在实例上找到的所有可调用对象都是方法。示例:x = SomeTest() x.lala = lambda arg : arg * 2
      • @Paul, dir 应该是这样做的方法。如果你用 dir 找不到它,它就不应该被找到。
      • 为什么不使用“callable”关键字而不是使用属性?
      • callable 已从 Python 3.x 中删除,但 hasattr 在 2.x 和 3.x 中均有效
      猜你喜欢
      • 1970-01-01
      • 2011-01-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-11-21
      • 2019-10-18
      相关资源
      最近更新 更多