Как связать вызовы функций Python, чтобы поведение было следующим

Я наткнулся на следующую проблему при вызове Python: написать функцию, которая удовлетворяет следующему правилу для любого числа вызовов функций.

f()()()()()(s) == 'fooooo' + s;

пример:

f('it') == 'fit';
f()('x') == 'fox';
f()()('bar') == 'foobar';
f()()()('l') == 'foool';

Функция должна быть без сохранения состояния и не должна использовать никаких переменных вне области видимости.

Подпись функции была:

def f(s=None):
    # Your code here

Я подумал, что для того, чтобы иметь возможность объединять несколько вызовов, нам придется возвращать функцию, когда в функцию не передана ни одна строка, но не могу понять, как построить ожидаемую строку без внешних переменных. Предложения?

def f(s=None):
    if s is None:
        # concatenate an 'o'?
        return f
    else:
        # Last call, return the result str.
        return s

Ответы

Ответ 1

Альтернатива Николау ответу что-то вроде этого:

def f(s=None):
    if s: return f'f{s}'

    def factory(prefix):
        def inner(s=None):
            return f'f{prefix}{s}' if s else factory(prefix + 'o')
        return inner
    return factory('o')

используя замыкание и без вспомогательной функции, но я бы предпочел partial решение.

Ответ 2

Очевидно, вам нужно хранить число "o" где-то в памяти (например, код) функции f. Чтобы достичь этого, вы можете воспользоваться этими двумя функциями Python:

  1. Вы можете определить функции внутри других функций
  2. Там это называется связыванием аргументов, которое позволяет вам сказать Python исправить некоторые или все аргументы вашей функции. Это делается через functools.partial

И вот решение

from functools import partial

def f(s=None):
    # Define a new function g which takes the current text and takes s
    def g(current_text, s=None):
        if s is not None:
            return current_text + s
        else:
            # If called with an empty argument, just rebind current_text with an extra o
            return partial(g, current_text + "o")

    # Just call g with the initial conditions
    return g("f", s)

print(f()()()()()("s")) # fooooos
print(f("s")) # fs

Ответ 3

Вы можете попробовать это:

def f(s=None):
    string = "f"
    def ret(p=None):
        nonlocal string
        string += "o"
        return ret if not p else string + p
    return ret if not s else string + s

Ответ 4

Это мой путь к этому:

def f(x=None, seq=''):
    if x:
        return 'f' + seq + x
    else:
        def g(y=None, p=seq + 'o'):
            return f(y, p)
        return g

Редактировать Если вам действительно нужно, чтобы сигнатура функции была f(x=None), используйте это:

def f(x=None):
    def f_(x=None, seq=''):
        if x:
            return 'f' + seq + x
        else:
            def g(y=None, p=seq + 'o'):
                return f_(y, p)
            return g
    return f_(x)

: ^)

Ответ 5

Просто для печати строки:

def f(s=None):
    def fo(s=None):
        if s==None:
            print('o',end='')
            return fo
        else:
            print(s)
            return
    if s!=None:
        print('f',end='')
        print(s)
        return
    elif s==None:
        print('fo',end='')
        return fo

Ответ 6

Как это:

def f(val=None):
    if val is not None:
        return 'f' + str(val)
    def inner1(val=None):
        if val is not None:
            return 'fo' + str(val)
        def inner2(val=None):
            if val is not None:
                return 'foo' + str(val)
            def inner3(val):
                return 'fooo' + str(val)
            return inner3
        return inner2
    return inner1

assert f('it') == 'fit'
assert f()('x') == 'fox'
assert f()()('bar') == 'foobar'
assert f()()()('l') == 'foool'

Ответ 7

Милая проблема. Это компактный способ сделать это:

def f(s=None, prefix="f"):
    if s: return prefix + s
    return lambda s=None: f(s, prefix=prefix+"o")

Ответ 8

Это действительно забавный вопрос. Я бы использовал изменяемый аргумент по умолчанию, чтобы решить это:

def f(s=None,l=[]):
    if not s:
        l.append("o")
        return f
    else:
        return "f"+"".join(l)+s

Ответ 9

FP:

f=lambda s=None,prefix='f':prefix+s  if s else lambda s=None,prefix=prefix+'o':f(s,prefix)