Закрытие Python и атрибуты функции - PullRequest
3 голосов
/ 26 января 2012

Я пытался переопределить что-то вроде partial (что позже будет иметь больше поведения). Теперь в следующем примере lazycall1 работает так же хорошо, как lazycall2, поэтому я не понимаю, почему документация partial предлагает использовать более длинную вторую версию. Какие-либо предложения? Может ли это доставить мне неприятности?

def lazycall1(func, *args, **kwargs):
    def f():
        func(*args, **kwargs)
    return f

def lazycall2(func, *args, **kwargs):
    def f():
        func(*args, **kwargs)
    f.func=func   # why do I need that?
    f.args=args
    f.kwargs=kwargs
    return f

def A(x):
    print("A", x)

def B(x):
    print("B", x)

a1=lazycall1(A, 1)
b1=lazycall1(B, 2)
a1()
b1()

a2=lazycall2(A, 3)
b2=lazycall2(B, 4)
a2()
b2()

РЕДАКТИРОВАТЬ: На самом деле ответы, данные до сих пор не совсем правильно. Даже с двойными аргументами это будет работать. Есть ли другая причина?

def lazycall(func, *args):
    def f(*args2):
        return func(*(args+args2))
    return f

def sum_up(a, b):
    return a+b

plusone=lazycall(sum_up, 1)
plustwo=lazycall(sum_up, 2)
print(plusone(6)) #7
print(plustwo(9)) #11

Ответы [ 3 ]

2 голосов
/ 26 января 2012

Единственное, что есть во второй форме, - это некоторые дополнительные свойства. Это может быть полезно, если вы начнете передавать функции, возвращаемые lazycall2, чтобы принимающая функция могла принимать решения на основе этих значений.

0 голосов
/ 26 января 2012

Посмотрите ближе на имена аргументов во внутренней функции newfunc на странице документации Python, на которую вы ссылаетесь, они отличаются от тех, которые передаются внутренней функции, args против fargs, keywords противfkeywords.Их реализация partial сохраняет аргументы, которые были переданы внешней функции, и добавляет их к аргументам, данным внутренней функции.

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

Что касается установки атрибутов func, args и kwargs для внешней функции, функция в Python является объектом, и вы можете установитьатрибуты на нем.Эти атрибуты позволяют вам получить доступ к исходной функции и аргументам после того, как вы передали их в ваши lazycall функции.Таким образом, a1.func будет A, а a1.args будет [1].

Если вам не нужно отслеживать исходную функцию и аргументы, вам будет хорошо с вашим lazycall1.

0 голосов
/ 26 января 2012

functools.partial может принимать дополнительные аргументы - или переопределенные аргументы - во внутренней возвращаемой функции. Ваши внутренние f() функции не работают, поэтому нет необходимости в том, что вы делаете в lazycall2. Однако, если вы хотите сделать что-то вроде этого:

def sum(a, b):
    return a+b
plusone = lazycall3(sum, 1)
plusone(6) # 7

Вам нужно сделать то, что показано в этих документах.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...