
[code]

    class test:
        def method1(self):
            print('1')
    
        def method2(self):
            print('2')
    
[/code]

というコードを、

[code]

    class test:
        methods = {}
    
        def method1(self):
            print('1')
        
        methods['m1'] = self.method1
    
        def method2(self):
            print('2')
    
        methods['m2'] = self.method2
    
[/code]

として、`x =
test()`に対して、`x.method1()`の代わりに`x.methods['m1']()`のようにkeyを指定してメソッドを実行できるようにしたいのですが、エラーが出てしまいます。（`NameError:
name 'self' is not defined`）

どのように変更すればよいでしょうか？


CC BY-SA 4.0
2021-09-11T09:08:03.413
82419
2021-09-12T12:38:53.137
48164
question
python
Pythonのクラスのメソッドを辞書にまとめたい


それを行って意味があるのか？とか、何か使い方に思わぬ制限がありそうな気がしますが、こんなパターンでの設定が考えられます。  
まだやり方はありそうですが、まずは一例として。

* * *

  * `__init__`メソッドで設定する

[code]

    class test:
        methods = {}
        
        def method1(self):
            print('1')
        
        def method2(self):
            print('2')
        
        def __init__(self):
            test.methods['m1'] = self.method1
            test.methods['m2'] = self.method2
    
    x = test()
    x.methods['m1']()
    x.methods['m2']()
    
[/code]

* * *

  * `__init__`メソッドで設定する、かつ`methods`もインスタンス変数とする

[code]

    class test:
        
        def method1(self):
            print('1')
        
        def method2(self):
            print('2')
        
        def __init__(self):
            self.methods = {}
            self.methods['m1'] = self.method1
            self.methods['m2'] = self.method2
    
    x = test()
    x.methods['m1']()
    x.methods['m2']()
    
[/code]

* * *

  * `self`は一切使わない

[code]

    class test:
        methods = {}
        
        def method1():
            print('1')
        
        methods['m1'] = method1
        
        def method2():
            print('2')
        
        methods['m2'] = method2
    
    x = test()
    x.methods['m1']()
    x.methods['m2']()
    
[/code]

* * *

  * 設定時には`self.`を使わない(=呼び出し時にインスタンスをselfとしてパラメータ指定する)

[code]

    class test:
        methods = {}
        
        def method1(self):
            print('1')
        
        methods['m1'] = method1
        
        def method2(self):
            print('2')
        
        methods['m2'] = method2
    
    x = test()
    x.methods['m1'](x)
    x.methods['m2'](x)
    
[/code]


CC BY-SA 4.0
2021-09-11T09:52:10.460
82421
2021-09-11T09:52:10.460
26370
82419
answer


以下はプロパティを使う方法です。

[code]

    class test:
      @property
      def methods(self):
        if not hasattr(self, '__methods__'):
          prefix = 'method'
          self.__methods__ = {
            m[0]+m[len(prefix):]: getattr(self, m) for m in dir(self)
            # Python 3.9 has str.removeprefix method
            # m[0]+m.removeprefix(prefix): getattr(self, m) for m in dir(self)
            if not isinstance(getattr(type(self), m), property)
               and m.startswith(prefix)
          }
        return self.__methods__
    
      def method1(self):
        print('1')
        
      def method2(self):
        print('2')
    
    if __name__ == '__main__':
      x = test()
      x.methods['m1']()
      x.methods['m2']()
    
    =>
    1
    2
    
[/code]


CC BY-SA 4.0
2021-09-11T10:39:02.743
82422
2021-09-12T02:14:03.440
2021-09-12T02:14:03.440
47127
47127
82419
answer


エラーが出ているのは、`self.method1` などと書かれている位置では `self` が定義されていないからです。

Python
の色々な[組み込み関数](https://docs.python.org/ja/3.9/library/functions.html)たちを使うと、クラスに定義されたメソッドたちを自動的に一覧することができます。

[code]

    class Test:
        def method_dict(self):
            self_class = type(self)
            name_and_funcs = map(lambda name: (name, getattr(self_class, name)), dir(self_class))
            return dict(filter(lambda nf: callable(nf[1]) and not nf[0].startswith("__"), name_and_funcs))
            
        def method1(self):
            print('1')
    
        def method2(self):
            print('2')
    
    print(Test().method_dict())
    # ==> {'method1': <function Test.method1 at 0x7f7fd8989310>, 'method2': <function Test.method2 at 0x7f7fd89893a0>, 'method_dict': <function Test.method_dict at 0x7f7fd8989280>}
    
[/code]

やりたいこと次第ですが、あとはキー名の生成規則を作れば質問者さんのやりたいことができるかもしれません。


CC BY-SA 4.0
2021-09-12T12:14:40.033
82441
2021-09-12T12:38:53.137
2021-09-12T12:38:53.137
19110
19110
82419
answer