coady / multimethod

Multiple argument dispatching.
https://coady.github.io/multimethod
Other
284 stars 23 forks source link

Does not work with multiple arguments in method of class #5

Closed ilirium closed 5 years ago

ilirium commented 5 years ago

Hi! I tried to use multimethod.multimethod to define several class methods, it works for one argument, however it doesn't work for more. For example:

from multimethod import multimethod

class Summary:
    @multimethod # line A
    def __init__(self, df: float, head: int, tail: int):
        self.df = df
        self.head = head
        self.tail = tail

    # block B
    @multimethod
    def __init__(self, df: dict, head: int, tail: int):
        self.df = df
        self.head = head
        self.tail = tail
    # end of block B

    @multimethod
    def __summary2(self, df: float):
        print(df * self.head * self.tail)

    @multimethod
    def __summary2(self, df: dict):
        for key in df:
            print(f'Name = {key}')
            print(df[key][self.head])
            print(df[key][self.tail])

    def summary(self):
        self.__summary2(self.df)

if __name__ == '__main__':
    print(f'Case No:1, Dictionary')
    df1 = [1, 2, 3, 10, 11, 12]
    df2 = [4, 5, 6, 13, 14, 15]
    df3 = [7, 8, 9, 16, 17, 18]
    dfs_dct = {'df1': df1, 'df2': df2, 'df3': df3}
    case_s1 = Summary(df=dfs_dct, head=0, tail=-1)
    print('case_s1')
    case_s1.summary()
    print(f'\n\n')

    print(f'Case No:2, List')
    df = 10.34
    case_s2 = Summary(df=df, head=0, tail=-1)
    print('case_s2')
    case_s2.summary()
    print(f'\n\n')

My environment: Python 3.7.4, Multimethod was installed from source, macOS 10.14.6.

Case No:1, Dictionary
Traceback (most recent call last):
  File "example03_3_args_built_in_types.py", line 40, in <module>
    case_s1 = Summary(df=dfs_dct, head=0, tail=-1)
  File "/path/to/multimethod/multimethod.py", line 108, in __call__
    return self[tuple(map(type, args))](*args, **kwargs)
  File "//path/to/multimethod/multimethod.py", line 104, in __missing__
    raise DispatchError("{}{}: {} methods found".format(self.__name__, types, len(keys)))
multimethod.DispatchError: __init__(<class '__main__.Summary'>,): 0 methods found

However, when I commented line A and block B, Case 1 is works.

Case No:1, Dictionary
case_s1
Name = df1
1
12
Name = df2
4
15
Name = df3
7
18

Case No:2, List
case_s2
Traceback (most recent call last):
  File "example03_3_args_built_in_types.py", line 50, in <module>
    case_s2.summary()
  File "example03_3_args_built_in_types.py", line 31, in summary
    self.__summary2(self.df)
  File "/path/to/multimethod/multimethod.py", line 108, in __call__
    return self[tuple(map(type, args))](*args, **kwargs)
  File "/path/to/multimethod/multimethod.py", line 104, in __missing__
    raise DispatchError("{}{}: {} methods found".format(self.__name__, types, len(keys)))
multimethod.DispatchError: __summary2(<class '__main__.Summary'>, <class 'float'>): 0 methods found

I also tried to use multimethod.multimeta and the func.register syntax, but the result was the same.

coady commented 5 years ago

It only dispatches on positional arguments. This will work: case_s1 = Summary(dfs_dct, 0, -1)

Keywords can be used when calling, but won't affect the dispatching.