私はこのコードを持っています:
class SomeClass:
@classmethod
def func1(cls,arg1):
#---Do Something---
@classmethod
def func2(cls,arg1):
#---Do Something---
# A 'function map' that has function name as its keys and the above function
# objects as values
func_map={'func1':func1,'func2':func2}
@classmethod
def func3(cls,arg1):
# following is a dict(created by reading a config file) that
# contains func names as keys and boolean as values that tells
# the program whether or not to run that function
global funcList
for func in funcList:
if funcList[func]==True:
cls.func_map[func](arg1) #TROUBLING PART!!!
if _name__='main'
SomeClass.func3('Argumentus-Primus')
これを実行すると、エラーが発生し続けます。
例外TypeError: "'classmethod'オブジェクトを呼び出せません"
私はこれの何が悪いのか理解することができません、そしてあなたの助けをいただければ幸いです。
クラスが定義されるまで、classmethodsへの参照を作成することはできません。クラス定義から移動する必要があります。ただし、グローバル関数マップを使用して何を実行するかを決定するのは非常に厄介です。これで何をしようとしているのかを説明していただければ、おそらくより良い解決策を提案できます。
class SomeClass(object):
@classmethod
def func1(cls, arg1):
print("Called func1({})".format(arg1))
@classmethod
def func2(cls, arg1):
print("Call func2({})".format(arg1))
@classmethod
def func3(cls, arg1):
for fnName,do in funcList.iteritems():
if do:
try:
cls.func_map[fnName](arg1)
except KeyError:
print("Don't know function '{}'".format(fnName))
# can't create function map until class has been created
SomeClass.func_map = {
'func1': SomeClass.func1,
'func2': SomeClass.func2
}
if __name__=='__main__':
funcList = {'func1':True, 'func2':False}
SomeClass.func3('Argumentus-Primus')
今夜、ここで役立つ何かを発見しました。getattr(func, '__func__')
を介して魔法のstaticmethod
オブジェクトとclassmethod
オブジェクトをアンラップできます。
この情報をどのように見つけましたか? JetBrainsのPyCharm(他のPython IDE)についてはわかりません)を使用して、_@staticmethod
_と_@classmethod
_のソースコードを表示しました。どちらのクラスも属性___func__
_。
"残りは読者の練習問題として残されています。"
Classmethodは、実際には呼び出せない魔法のオブジェクトで特定の関数をラップします。 ClassName.method(args)
構文を使用してのみ呼び出すことができます。
この方法で行うことはお勧めしません。代わりに次のようなことを検討してください。
func_list = {
'func1': True,
'func2': False
}
class SomeClass(object):
def do_func1(self, arg1):
print("func1", arg1)
def do_func2(self, arg1):
print("func2", arg1)
def run(self, arg1):
for name, enabled in func_list.items():
if enabled:
the_method = getattr(self, 'do_' + name)
the_method(arg1)
if __== '__main__':
sc = SomeClass()
sc.run('Argumentus-Primus')
他のすべての回答は、class SomeClass
定義の外にコードを追加することを提案しています。場合によっては大丈夫かもしれませんが、私の場合は非常に不便でした。 func_map
をクラス内に保持したかったのです。
次のアプローチをお勧めします。クラス変数ではなく、もう1つのclassmethodを使用します。
class SomeClass:
# ...
@classmethod
def get_func_map(cls):
return {'func1': cls.func1, 'func2': cls.func2}
@classmethod
def func3(cls, arg1):
# .....
cls.get_func_map()[func_name](arg1)
もちろん、get_func_map
メソッドを呼び出すたびに新しい辞書が作成されないように、このコードを変更する必要があります。簡単です。例を小さく明確にするために自分でやったわけではありません。
python 3.6でテスト済み
クラス内の各メソッドの引数としてselfを追加します。
また
if _name__='main'
SomeClass.func3('Argumentus-Primus')
次のようになります。
if __name__=='__main__':
SomeClass.func3('Argumentus-Primus')
クラスの本体内にあるべきではありません。
これを行うには悪い方法があります:
def func3(cls,arg1):
global funcList
for func in funcList:
if funcList[func]==True:
eval(f'SomeClass.{func}')(arg1)
Funcが関数の名前である場合にのみ機能します。そうは言っても、しないでくださいユーザー入力を取得しているため、このメソッドを使用してください。呼び出しに厄介なコードを挿入するのは非常に簡単です。そうは言っても、これは機能します。
静的メソッドを試す必要があるかもしれません。
@staticmethod
def function():...
静的メソッドは、暗黙の最初の引数としてクラスを渡しません。