Python / IronPython对象方法循环

4

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

给定对象:

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

1
你为什么不使用unittest模块呢?它可以为你完成这个任务。 - S.Lott
2
我正在尝试学习Python的内省/反射,而不是单元测试。虽然我意识到这看起来像是我正在尝试做的事情。 - BuddyJoe
4个回答

10
您可以使用`inspect`模块来获取类(或实例)成员:
>>> 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() 的第二个参数是谓词(predicate),它过滤返回的列表(在这种情况下仅返回方法对象)。


4
方法与函数以及其他类型的可调用对象…
(针对Unknown帖子中评论中的问题。)
首先,需要注意的是,除了用户定义的方法之外,还有内置方法,并且内置方法是如 http://docs.python.org/reference/datamodel.html 所说,“实际上是内置函数的不同伪装”(它是一个包装器,围绕一个C函数)。
至于用户定义的方法,就像Unknown引用的语录所说的那样:
用户定义的方法对象结合了类、类实例(或None)和任何可调用对象(通常是用户定义的函数)。
但这并不意味着“定义了__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__方法的每个对象都是一个“可调用对象”。(通过简单地定义call,您可以像函数一样执行任何对象)。命题3:因此,定义了__call__并附加到一个对象上的每个对象都是一个“用户定义的方法”。根据定义,“用户定义的方法”是一个方法。因此,在对象上附加时,“可调用对象不一定是一个方法”的引述是完全错误的。 - Unknown
我还想指出的是,通常定义的方法和猴子补丁方法之间存在明显的区别。然而,这并不否定附加到对象的可调用项是方法的事实。它不管它是否是特定类型。它不管它是否绑定到特定实例。实际上,你可悲的努力中的例子已经在你忽略的手册中描述过了,除了不像你一样,它仍然将这些东西称为方法。再看一下链接,阅读以...开头的段落。 - Unknown
当通过检索创建用户定义的方法对象时,您将看到我所说的。 - Unknown

0

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


-1

编辑

Daniel,你错了。

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

用户定义的方法
用户定义的方法对象结合了一个类、一个类实例(或None)和任何可调用对象(通常是用户定义的函数)。
因此,任何定义了__call__并附加到对象上的内容都是方法。
查看对象具有哪些元素的正确方法是使用dir()函数。
显然,这个示例仅适用于不带参数的函数。
a=SomeTest()
for varname in dir(a):
    var = getattr(a, varname)
    if hasattr(var, "__call__"):
        var()

2
dir()可能不是完成此操作的最佳方式,因为dir()不能保证获取每个成员,它只会尝试获取“有趣”的成员。但这肯定是一个开始。 - Paul Fisher
并非所有在实例上找到的可调用对象都是方法。例如:x = SomeTest() x.lala = lambda arg : arg * 2 - Daniel Ribeiro
@Paul,dir 命令应该是解决这个问题的方法。如果你在 dir 命令中找不到它,那么它就不应该被找到。 - Unknown
1
为什么不使用“callable”关键字而是使用属性呢? - Rohit
1
callable在Python 3.x中已被移除,但hasattr在2.x和3.x版本中都可使用。 - Anon
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接