通过getattr抛出访问的绑定Python方法:";不接受任何参数(给定1个)“;
在绑定方法、继承和getattr之间的交互中发生了一些我不理解的奇怪的事情 我有一个目录设置,如:通过getattr抛出访问的绑定Python方法:";不接受任何参数(给定1个)“;,python,class,getattr,Python,Class,Getattr,在绑定方法、继承和getattr之间的交互中发生了一些我不理解的奇怪的事情 我有一个目录设置,如: /a __init__.py start_module.py /b __init__.py imported_module.py 导入的_module.py包含许多类对象,其中一个是以下形式: class Foo(some_parent_class): def bar(self): return [1,2,3] start_module.py中的函数使用in
/a
__init__.py
start_module.py
/b
__init__.py
imported_module.py
导入的_module.py包含许多类对象,其中一个是以下形式:
class Foo(some_parent_class):
def bar(self):
return [1,2,3]
start_module.py中的函数使用inspect获取表示导入的_module.py中的类的字符串列表。“Foo”是这些字符串中的第一个。目标是使用该字符串和getattr在start_module.py中运行bar*
为此,我使用表单的start_模块中的代码:
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自动拥有对名称栏所有方法的访问权限,这些方法跨各种类,类似于导入的_module.py中的Foo。我这样做是希望避免让我的继任者维护一个可能是大量类似Foo的类的列表
下面回答:我认为这里最大的收获是,inspect非常有用,如果您遇到的bug有一个共同的原因,那么在继续搜索其他可能性之前,请确保您已经排除了这一点。在本例中,我忽略了一个事实,即由于最近对文件结构进行了编辑,我正在查看的具有正确代码的模块可能不是正在导入的模块。类方法有一个基本上自动传递的
self
参数。它只是调用方法的类实例。您不需要传递另一个参数。类方法有一个基本上自动传递的self
参数。它只是调用方法的类实例。您不需要传递另一个参数。因为您发布的示例代码是错误的,我猜您在某处有另一个带有Foo类的模块-可能bar
是这样定义的
class Foo(object):
def bar(): # <-- missing self parameter
return [1,2,3]
类Foo(对象):
def bar():#>>Foo().bar()
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
TypeError:bar()不接受任何参数(给定1个)
由于您发布的示例代码是错误的,我猜您在某处有另一个带有Foo类的模块-可能bar
是这样定义的
class Foo(object):
def bar(): # <-- missing self parameter
return [1,2,3]
类Foo(对象):
def bar():#>>Foo().bar()
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
TypeError:bar()不接受任何参数(给定1个)
我无法重现您遇到的错误。下面是我尝试从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!
也许您可以尝试将基于
的代码修改为类似于此示例的代码,看看哪里出了问题。我无法重现您得到的错误。下面是我尝试从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
的代码改编成这样的示例,看看哪里出了问题。return=[1,2,3]
不是有效的Python。请确保您发布的是您正在使用的实际代码。为Foo
创建一个元类可能是一个更好的主意,该元类可以“注册”所有bar
,例如,将它们存储在列表中。很抱歉。修好它。我以一种非常简单的形式添加了类描述,以使其易读,并意外地插入了一个额外的字符。我同意gnibbler的观点。这根本不能解决问题的要点,但是在[x for x in function()]
中对doodad的列表理解是完全不必要的。只需在函数()中为doodad使用
return=[1,2,3]
不是有效的Python。请确保您发布的是您正在使用的实际代码。为Foo
创建一个元类可能是一个更好的主意,该元类可以“注册”所有bar
,例如,将它们存储在列表中。很抱歉。修好它。我以一种非常简单的形式添加了类描述,以使其易读,并意外地插入了一个额外的字符。我同意gnibbler的观点。这根本不能解决问题的要点,但是在[x for x in function()]中对doodad的列表理解是完全不必要的。只需在函数()中为doodad使用
!有问题的调用是function(),它没有获取另一个参数。有问题的调用是function(),它没有获取另一个参数。我希望是这样。我只是后退了一步,再次仔细检查了一下,bar和它覆盖的函数都用self-include编码。对于示例代码,很抱歉。@TimWilder:(1)在for
循环显示它应该显示的代码之前,print inspect.getsource(函数)
?(2) 在python-tt
下运行时,您的代码是否工作(以排除由于空格不一致而可能出现的缩进错误)?(3) 如果没有,那么我想你必须建造一个。我明天去看看。很好的建议。问题是在我昏昏欲睡的时候,我移动了imported_module.py,并用start_module导入了移动的副本。我还在编辑那本旧书。DSM的建议