1

在我无法理解的绑定方法、继承和 getattr 之间的交互中发生了一些相当奇怪的事情。

我有一个目录设置,如:

/a
__init__.py
start_module.py
  /b
  __init__.py
  imported_module.py 

import_module.py 包含许多类对象,其中一个是这种形式:

class Foo(some_parent_class):
    def bar(self):
       return [1,2,3]

start_module.py 中的一个函数使用inspect 来获取表示imported_module.py 中的类的字符串列表。“Foo”是这些字符串中的第一个。目标是使用该字符串和 getattr.* 在 start_module.py 中运行 bar

为此,我使用以下形式的 start_module 代码:

for class_name in class_name_list:
  instance = getattr(b.imported_module, class_name)()
  function = getattr(instance, "bar")
  for doodad in [x for x in function()]:
     print doodad 

它确实成功地开始迭代列表理解,但是在第一个字符串“bar”上,我得到了一个奇怪的错误。尽管 bar 是一个绑定方法,据我所知,期望 Foo 的实例作为参数,我被告知:

TypeError: bar() 不接受任何参数(给定 1 个)

这使得我对 function() 的调用似乎传递了 Foo 实例,但代码并不期望接收它。

我真的不知道这里发生了什么,也无法通过查看 Google 和 Stack Overflow 来解析出一个解释。双重 getattr 是否会导致一些奇怪的交互?我对 Python 中的类对象的理解是否过于模糊?我很想听听你的想法。

*为了避免反模式,真正的最终目标是让 start_module.py 自动访问各种类的名称栏的所有方法,类似于 import_module.py 中的 Foo。我这样做是为了避免让我的继任者维护一个可能非常多的类似 Foo 的类的列表。

回答如下:我认为这里最大的收获是检查非常有用,如果您遇到的错误有共同的原因,请在继续寻找其他可能性之前绝对确保您已经排除了这种可能性。在这种情况下,我忽略了一个事实,即我正在查看的具有正确代码的模块可能不是由于最近对文件结构进行的编辑而被导入的模块。

4

3 回答 3

3

由于您发布的示例代码是错误的,我猜您在某处有另一个带有 Foo 类的模块 - 可能bar是这样定义的

class Foo(object):
    def bar():   # <-- missing self parameter
        return [1,2,3]

这确实给出了错误消息

>>> Foo().bar()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: bar() takes no arguments (1 given)
于 2013-01-10T01:34:49.107 回答
2

类方法有一个self本质上是自动传递的参数。它只是您调用该方法的类实例。您不需要传递另一个参数。

于 2013-01-10T01:28:28.440 回答
2

我无法重现您遇到的错误。这是我对一个简短的、自包含的可编译示例的尝试,从 Python shell 运行:

>>> class Foo(object):
    def bar(self):
        print("Foo.bar!")

>>> import __main__ as mod
>>> cls = getattr(mod, "Foo")
>>> inst = cls()
>>> func = getattr(inst, "bar")
>>> func()
Foo.bar!

也许您可以尝试将您inspect的基础代码调整为像这样的示例,看看哪里出了问题。

于 2013-01-10T03:29:33.813 回答