我有一个由
生成的python3对象(类实例)myObj = myClass()
线。我还有一个myMethodName
字符串:
myMethodName = "exampleName"
。如何调用由myObj
命名的myMethodName
方法?因此,在这种情况下,我想调用myObj.exampleName
,它来自getAttr(myObj, myMethodName)
。
不幸的是,python文档引用的一个天真的解决方案(例如,here)只给我一个KeyError
或AttributeError
。
这失败了myObj没有method
方法:
method = getAttr(myObj, myMethodName)
myObj.method(param)
失败的原因是myMethodName
的参数更少:
method = getAttr(myObj, myMethodName)
method(myObj, param)
简单地打电话
method = getAttr(myObj, myMethodName)
method(param)
哪个是最符合逻辑的,给出
TypeError: exampleName() takes 1 positional argument but 2 were given
那么,我该怎么做呢?
我使用python 3.6,如果重要的话。
扩展:这是一个MCVE:
class Test:
name = None
def __init__(name):
self.name = name
def process():
method = getattr(self, 'process_' + name)
method("param")
def process_test(param):
print ("process_test(): "+param)
test = Test("cica")
test.process("test")
答案 0 :(得分:2)
如果传递给getattr()
的属性是方法名,那么它返回一个已绑定到该对象的可调用对象:
getattr(object, name[, default])
返回object的named属性的值。
name
必须是字符串。如果字符串是其中一个object
的名称 属性,结果是该属性的值。 例如,getattr(x, 'foobar')
相当于x.foobar
。如果命名 如果提供了属性,则返回default
,否则返回AttributeError
被提出。
证明:
>>> x = [1, 2, 1, 3, 1, 1]
>>> f = getattr(x, 'count') # same as f = x.count
>>> f(1)
4
答案 1 :(得分:2)
您的示例可以针对以下内容进行更改:
class Test:
def __init__(self, name):
self.name = name
def process(self, param):
method = getattr(self, 'process_' + param)
method("param")
def process_test(self, param):
print ("process_test(): "+param)
test = Test("cica")
test.process("test")
我认为你缺少Python中绑定/静态方法的概念。请参阅此answer,它描述了不同类型的方法。
答案 2 :(得分:1)
导致第一个错误,因为getattr
返回已绑定到对象实例(myObj
)的方法。
所以你要做的就是把你的method
变量称为函数。
第二个错误可能是由于您的exampleName没有与传递给method
的参数数量相同的参数数量。
第二个错误所需要做的就是在类中的方法中添加相同的参数:
myObj = myClass()class myClass:
def exampleName(self, *args, **keyargs):
print('Method exampleName was called')
myObj = myClass()
myMethodName = "exampleName"
method = getattr(myObj, myMethodName)
method('some param')
更新
您添加的示例中还有一些问题:
class Test:
# This was removed, as you already initialize the instance variable in the constructor.
# Setting it here would cause the variable to be shared by all instances of the class,
# which you probably do not want, as you are passing the value as argument to the constructor below.
# name = None
# You missed to add the self parameter
def __init__(self, name):
self.name = name
# Again, self parameter was missed
# Additionally, we added a `suffix` parameter, that will accept the `test` value from the `process` call
# We also added *args and **keyargs that will accept arbitrary number of parameters. Those will be
# passed down to the `process_test` method.
def process(self, suffix, *args, **keyargs):
# We use the `suffix` parameter here, (instead of `name`)
method = getattr(self, 'process_' + suffix)
method(*args, **keyargs)
def process_test(self, param):
print("process_test(): " + param)
test = Test("cica")
test.process("test", "some param")