Как может работать этот функциональный код python?

StackOverflow https://stackoverflow.com/questions/1463588

  •  13-09-2019
  •  | 
  •  

Вопрос

это взято из исходного кода csv2rec в matplotlib

как может работать эта функция, если ее единственными параметрами являются 'func, default'?

def with_default_value(func, default):
    def newfunc(name, val):
        if ismissing(name, val):
            return default
        else:
            return func(val)
    return newfunc

ismissing принимает имя и значение и определяет, должна ли строка быть замаскирована в массиве numpy.

функция будет либо иметь значение str, int, float, либо dateparser...it преобразует данные.Может быть, и не важно.Мне просто интересно, как он может получить "имя" и "значение"

Я новичок.Спасибо за любые 2цента!Я надеюсь стать достаточно хорошим, чтобы помогать другим!

Это было полезно?

Решение

Это with_default_value функция - это то, что часто называют (неточно) "замыканием" (технически, замыкание - это скорее внутренний функция, которая возвращается, здесь newfunc -- см . , например , здесь).В более общем смысле, with_default_value является функция более высокого порядка ("HOF"):для этого требуется функция (func) в качестве аргумента он также возвращает функцию (newfunc) в результате.

Я видел ответы, путающие это с декоратор концепция и конструкция на Python, которая определенно не по делу - особенно после того , как вы упомянули func так же часто являясь встроенным, таким как int.Декораторы также являются функциями более высокого порядка, но довольно специфичными:те, которые возвращают оформленный, т. е."обогащенная" версия аргумента их функции (которая должна быть Только аргумент - "декораторы с аргументами" получаются через еще один уровень вложенности функции / замыкания, не предоставляя декоратору более одного аргумента), которому присваивается точно такое же имя, что и у этого аргумента функции (и поэтому обычно имеет ту же подпись - использование декоратора в противном случае было бы чрезвычайно своеобразный, неидиоматичный, нечитаемый и т.д.).

Поэтому забудьте о декораторах, которые не имеют абсолютно никакого отношения к делу, и сосредоточьтесь на newfunc завершение.Лексически вложенная функция может ссылаться (хотя и не привязывать повторно) на все имена локальных переменных (включая имена аргументов, поскольку аргументы являются локальными переменными) заключающей функции (ов) - вот почему она известна как замыкание:он "закрыт" над этими "свободными переменными".Здесь, newfunc может ссылаться на func и default -- и делает.

Функции более высокого порядка - очень естественная вещь в Python, особенно с учетом того, что функции являются объектами первого класса (поэтому вам не нужно ничего особенного делать, чтобы передавать их в качестве аргументов, возвращать их как значения функции или даже хранить их в списках или других контейнерах и т.д.), И нет различия в пространстве имен между функциями и другими типами объектов, нет автоматического вызова функций только потому, что они упомянуты, и т.д. и т.п.(Это сложнее - немного сложнее или НАМНОГО сложнее, в зависимости от того - в других языках, которые проводят множество различий такого рода).В Python упоминание функции - это просто упоминание;вызов выполняется только в том случае, если за объектом функции (на который ссылаются по имени или иным образом) следуют круглые скобки.

Вот, пожалуй, и все, что есть в этом примере - пожалуйста, не стесняйтесь редактировать свой вопрос, комментировать здесь и т.д., если есть какой-то другой конкретный аспект, в котором вы по-прежнему сомневаетесь!

Редактировать:итак, ОП вежливо прокомментировала ситуацию, попросив привести еще примеры "фабрик закрытия".Вот один из них - представьте себе какой-то абстрактный набор инструментов GUI, и вы пытаетесь сделать:

for i in range(len(buttons)):
  buttons[i].onclick(lambda: mainwin.settitle("button %d click!" % i))

но это работает неправильно -- i в пределах lambda привязан к концу, поэтому к моменту нажатия одной кнопки iзначением s всегда будет индекс Последние кнопка, независимо от того, какая из них была нажата.Существуют различные возможные решения, но укупорочная фабрика - это элегантная возможность:

def makeOnclick(message):
  return lambda: mainwin.settitle(message)

for i in range(len(buttons)):
  buttons[i].onclick(makeOnClick("button %d click!" % i))

Здесь мы используем фабрику закрытия, чтобы настроить время привязки переменных!-) В той или иной конкретной форме это довольно распространенный вариант использования для фабрик закрытия.

Другие советы

Это декоратор Python - по сути, оболочка функции.(Читайте все о декораторах в PEP 318 -- http://www.python.org/dev/peps/pep-0318/)

Если вы просмотрите код, вы, вероятно, найдете что-то вроде этого:

def some_func(name, val):
    # ...
some_func = with_default_value(some_func, 'the_default_value')

Намерение этого декоратора, по-видимому, предоставить значение по умолчанию, если отсутствуют аргументы name или val (предположительно, если для них установлено значение None).

Что касается того, почему это работает:

with_default_value возвращает объект функции, который в основном будет Копировать из этого вложенного newfunc, с вызовом 'func' и значением по умолчанию, замененным тем, что было передано в with_default_value .

Если кто-то сделает 'foo = with_default_value(bar, 3)', возвращаемое значение в основном будет новой функцией:

def foo(name, val):
    ifismissing(name, val):
        return 3
    else:
        return bar(val)

таким образом, затем вы можете взять это возвращаемое значение и вызвать его.

Это функция, которая возвращает другую функцию. name и value являются параметрами возвращаемой функции.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top