循环 Python / IronPython 对象方法

Posted

技术标签:

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

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

给定对象:

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

【问题讨论】:

你为什么不使用 unittest 模块,它会为你做这件事? 尝试学习 Python 内省/反射而不是单元测试。虽然我意识到这就是我正在尝试做的事情。 【参考方案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 中均有效

以上是关于循环 Python / IronPython 对象方法的主要内容,如果未能解决你的问题,请参考以下文章

C++\IronPython 集成示例代码?

初步了解IronPython

安装ironpython

Python学习-环境搭建(IronPython)

MS SQL + Python (IronPython) 超时

Ironpython调用numpy问题