2017-02-03 8 views
-3

Iは名前で指定されたオブジェクトのメソッドを文字列として呼び出す方法は?

myObj = myClass() 

線によって生成される、のpython3オブジェクト(クラスのインスタンス)を有します。私はmyMethodName文字列も持っています:

myMethodName = "exampleName" 

です。 myMethodNameという名前のメソッドを呼び出すには、どうすればよいですか?myObjしたがって、この場合、myObj.exampleNameに電話をかけたいと思います。これはgetAttr(myObj, myMethodName)のようになります。

残念ながら、Pythonドキュメント(たとえば、here)を参照する単純な解決策では、唯一のKeyErrorまたはAttributeErrorが得られます。これは、そのmyMethodNameに失敗し

method = getAttr(myObj, myMethodName) 
myObj.method(param) 

少ない引数のよりました:

method = getAttr(myObj, myMethodName) 
method(myObj, param) 

は単に

method = getAttr(myObj, myMethodName) 
method(param) 
を呼び出す

これは、このmyobjはmethodメソッドを持っていないことに失敗しました最も論理的である

は、

TypeError: exampleName() takes 1 positional argument but 2 were given 

どうすればいいですか?

問題がある場合は、私はpython 3.6を使用します。 getattr既にオブジェクトインスタンス(myObj)に結合されている方法を返すため、最初のエラーが発生し

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") 
+2

あなたの 'method'はすでにメソッドです。' method(params) 'のように呼び出すことはできませんか?あなたがMCVEを提供していれば、私はそれを自分自身でテストしたいと思っています。 –

+0

@StefanPochmannまた、これは誤りです。私はそれを質問に拡張しました。 – peterh

+0

@StefanPochmann MCVEが追加されました。 – peterh

答えて

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を参照してください。さまざまな種類のメソッドについて説明しています。

+0

申し訳ありませんが、 'process_ *'関数を 'self'でパラメータ化するのを忘れてしまいました... – peterh

1


拡張:ここMCVEあります。

あなたがしなければならないことは、関数であるかのように変数methodを呼び出すことだけです。

2番目のエラーは、おそらくexampleNameが、methodに渡された引数の数と同じ数のパラメータを持たないことが原因です。

あなたが2番目のエラーのためにしなければならないのは、クラス内のメソッドに同じパラメータを追加することです:

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") 
+0

マイナーフォーマットの修正、それは大丈夫です願っています。今私はテストしている。 – peterh

+0

私はあなたがそれを元に戻ったのを見ます、それは正しい構文ですか? – peterh

+0

ありがとう!解決策が見つかりました、それは些細な問題でした。 – peterh

2

getattr()に渡された属性は、メソッド名である場合、それはすでにオブジェクトにバインドされている呼び出し可能を返します。

getattr(object, name[, default])

Return the value of the named attribute of object. name must be a string. If the string is the name of one of the object ’s attributes, the result is the value of that attribute. For example, getattr(x, 'foobar') is equivalent to x.foobar. If the named attribute does not exist, default is returned if provided, otherwise AttributeError is raised.

証明:

>>> x = [1, 2, 1, 3, 1, 1] 
>>> f = getattr(x, 'count') # same as f = x.count 
>>> f(1) 
4 
+0

結果: 'TypeError:exampleName()は1つの位置引数を取るが、2つは与えられる '。注:これは組み込みクラスではなく、私が定義したクラスです。 – peterh

+0

@peterhあなたの問題は、メソッドのシグネチャに 'self'仮引数を指定しないことです。 [Jacques Gaudinの答え](http://stackoverflow.com/users/1388292/jacques-gaudin)はその問題を解決します。 – Leon

+0

正確に解決しました。ありがとう! – peterh

関連する問題