Pergunta

Esta é a partir do código-fonte do csv2rec em matplotlib

Como pode esta função de trabalho, se seus únicos parâmetros são '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 leva um nome e um valor e determina se a linha deve ser mascarado em uma matriz numpy.

func será ou str, int, float, ou dateparser ... ele converte dados. Talvez não é importante. Eu só estou querendo saber como ele pode obter um 'nome' e um 'valor'

Eu sou um novato. Obrigado por todas as 2cents! Espero conseguir bons o suficiente para ajudar os outros!

Foi útil?

Solução

Esta função with_default_value é o que é muitas vezes referida (imprecisa) como "um fecho" (tecnicamente, o fechamento é antes o interior função que será devolvida, aqui newfunc - ver, por exemplo aqui ). Mais genericamente, with_default_value é uma função de ordem superior ( "HOF."): É preciso uma função (func) como um argumento, ele também retorna uma função (newfunc) como o resultado

Já vi respostas confundindo isso com o decorador conceito e construção em Python, que é definitivamente não o caso - especialmente desde que você menciona func como muitas vezes ser um embutida tal como int. Decoradores também são funções de ordem superior, mas aqueles bastante específicas: os que retornam um decorado, ou seja, "enriquecido", versão de seu argumento de função (que deve ser o única argumento - "decoradores com argumentos" são obtidos através de mais um nível de aninhamento função / fechamento, não , dando a HOF decorador mais de um argumento), que fica transferido para exatamente o mesmo nome que o argumento da função (e assim normalmente tem o mesmo assinatura -. usando um decorador de outra forma seria extremamente peculiar, não-idiomática, ilegível, etc)

Portanto, esqueça decoradores, que não têm absolutamente nada a ver com o caso, e o foco sobre o encerramento newfunc. Uma função lexically aninhada pode referir-se (embora não rebind) todos os nomes de variáveis ??locais (incluindo nomes de argumentos, uma vez que os argumentos são variáveis ??locais) da função delimitador (s) - É por isso que é conhecido como um fecho: É "fechou-se sobre" estes "variáveis ??livres". Aqui, newfunc pode se referir a func e default -. E faz

funções de ordem superior são uma coisa muito natural em Python, especialmente porque as funções são objetos de primeira classe (então não há nada de especial que você precisa fazer para passá-las como argumentos, devolvê-los como valores de função, ou mesmo armazená-los em listas ou outros recipientes, etc), e não há nenhuma distinção namespace entre funções e outros tipos de objetos, nenhuma chamada automática de funções só porque eles são mencionados, etc, etc. (é mais difícil - um pouco mais difícil, ou muito mais difícil, dependendo - em outros idiomas que fazem sorteio de distinções desse tipo). Em Python, mencionando uma função é apenas isso - uma menção; CALL só acontece se e quando o objeto de função (referido pelo nome, ou de outra forma) é seguido por parênteses.

Isso é tudo o que há para este exemplo - por favor, fique à vontade para editar a sua pergunta, comentário aqui, etc, se há algum outro aspecto específico que você permaneça em dúvida sobre

Editar : assim que o OP comentou educadamente pedindo mais exemplos de "fábricas de fechamento". Aqui está uma - imagine algum tipo abstrato de GUI toolkit, e você está tentando fazer:

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

mas isso não funciona direito - i dentro do lambda é tardia, por isso, o tempo de um botão é clicado valor de i é sempre vai ser o índice do última botão, não importa qual deles foi clicado. Existem várias soluções viáveis, mas uma fábrica de fechamento é uma possibilidade elegante:

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

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

Aqui, estamos usando a fábrica de fechamento para ajustar o tempo de ligação de variáveis ??-!). Em uma forma específica ou de outra, este é um caso de uso muito comum para as fábricas de fechamento

Outras dicas

Este é um decorador Python - basicamente um invólucro de função. (Leia tudo sobre decoradores em PEP 318 - http://www.python.org / dev / peps / pep-0318 / )

Se você olhar através do código, você provavelmente vai encontrar algo parecido com isto:

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

A intenção deste decorador parece fornecer um valor padrão se o nome ou argumentos val estão faltando (presumivelmente, se eles são definidos como Nenhum).

Quanto ao porquê de ele funciona:

with_default_value retorna uma função de objeto, que é basicamente vai ser um Copiar de que newfunc aninhada, com a chamada 'func' eo valor padrão substited com o que foi passado para with_default_value.

Se alguém faz 'foo = with_default_value (bar, 3)', o valor de retorno é basicamente vai ser uma nova função:

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

para que você possa, em seguida, tomar esse valor de retorno, e chamá-lo.

Esta é uma função que retorna outra função. name e value são os parâmetros da função retornado.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top