What is the most pythonic way to make a related method act as a function?

I use the Python API, which expects me to pass a function to it. However, for various reasons, I want to pass the method to it, because I want the function to behave differently depending on the instance to which it belongs. If I pass a method to it, the API will not call it the correct argument, “I”, so I'm wondering how to turn the method into a function that knows which “I” it belongs to.

There are several ways that I can come up with for this, including using lambda and closing. I have provided some examples of this below, but I am wondering if there is a standard mechanism for achieving the same effect.

class A(object):
    def hello(self, salutation):
        print('%s, my name is %s' % (salutation, str(self)))

    def bind_hello1(self):
        return lambda x: self.hello(x)

    def bind_hello2(self):
        def hello2(*args):
            self.hello(*args)
        return hello2


>>> a1, a2 = A(), A()
>>> a1.hello('Greetings'); a2.hello('Greetings')
Greetings, my name is <__main__.A object at 0x71570>
Greetings, my name is <__main__.A object at 0x71590>

>>> f1, f2 = a1.bind_hello1(), a2.bind_hello1()
>>> f1('Salutations'); f2('Salutations')
Salutations, my name is <__main__.A object at 0x71570>
Salutations, my name is <__main__.A object at 0x71590>

>>> f1, f2 = a1.bind_hello2(), a2.bind_hello2()
>>> f1('Aloha'); f2('Aloha')
Aloha, my name is <__main__.A object at 0x71570>
Aloha, my name is <__main__.A object at 0x71590>
+3
2

, ? , .

In [2]: class C(object):
   ...:     def method(self, a, b, c):
   ...:         print a, b, c
   ...:
   ...:

In [3]: def api_function(a_func):
   ...:     a_func("One Fish", "Two Fish", "Blue Fish")
   ...:
   ...:

In [4]: c = C()

In [5]: api_function(c.method)
One Fish Two Fish Blue Fish
+8

. ,

def callback(fn):
    fn('Welcome')
callback(a1.hello)
callback(a2.hello)

hello self, a1 a2. , - , Python.

, , , , , , - - , currying, , 52549 Pythonic, .

class curry:
    def __init__(self, fun, *args, **kwargs):
        self.fun = fun
        self.pending = args[:]
        self.kwargs = kwargs.copy()

    def __call__(self, *args, **kwargs):
        if kwargs and self.kwargs:
            kw = self.kwargs.copy()
            kw.update(kwargs)
        else:
            kw = kwargs or self.kwargs

        return self.fun(*(self.pending + args), **kw)

f1 = curry(a1.hello, 'Salutations')
f1()  #  == a1.hello('Salutations')
0

Source: https://habr.com/ru/post/1702400/


All Articles