Eu tenho uma variável, x
e quero saber se está apontando para uma função ou não.
Eu esperava poder fazer algo como:
>>> isinstance(x, function)
Mas isso me dá:
Traceback (most recent call last):
File "<stdin>", line 1, in ?
NameError: name 'function' is not defined
A razão pela qual escolhi isso é porque
>>> type(x)
<type 'function'>
insepct.getsource
em uma variedade de objetos, e na verdade não importa se o objeto era passível de chamada, mas se era algo que daria 'função'type(obj)
. Como o google me levou até aqui, eu diria que o comentário do AsTeR foi a resposta mais útil (para mim). Existem muitos outros lugares na internet para as pessoas descobrirem__call__
oucallable
.Respostas:
Se for para o Python 2.x ou para o Python 3.2+, você também pode usar
callable()
. Ele era obsoleto, mas agora não é obsoleto, para que você possa usá-lo novamente. Você pode ler a discussão aqui: http://bugs.python.org/issue10518 . Você pode fazer isso com:Se for para o Python 3.x, mas antes do 3.2, verifique se o objeto tem um
__call__
atributo. Você pode fazer isso com:A
types.FunctionTypes
abordagem frequentemente sugerida não está correta porque falha em cobrir muitos casos que você provavelmente gostaria que ela passasse, como acontece com os builtins:A maneira correta de verificar as propriedades de objetos com tipo de pato é perguntar se eles grasnam, não para ver se eles se encaixam em um contêiner do tamanho de pato. Não use a
types.FunctionType
menos que tenha uma idéia muito específica do que é uma função.fonte
Tipos internos que não têm construtores no espaço de nomes interno (por exemplo, funções, geradores, métodos) estão no
types
módulo. Você pode usartypes.FunctionType
em umaisinstance
chamada:Observe que isso usa uma noção muito específica de "função" que geralmente não é o que você precisa. Por exemplo, ele rejeita
zip
(tecnicamente uma classe):open
(as funções incorporadas têm um tipo diferente):e
random.shuffle
(tecnicamente, um método de umarandom.Random
instância oculta ):Se você estiver fazendo algo específico para
types.FunctionType
instâncias, como descompilar seu bytecode ou inspecionar variáveis de fechamento, usetypes.FunctionType
, mas se você precisar apenas de um objeto que possa ser chamado como uma função, usecallable
.fonte
isinstance(f, (types.FunctionType, types.BuiltinFunctionType, functools.partial))
ou verificarf.func
nesse caso.@foo
que eu possa usar como@foo
e como@foo(some_parameter)
. Ele precisa verificar como está sendo chamado, por exemplo, a função para decorar (primeiro caso) ou o parâmetro (o segundo caso, no qual ele precisa retornar um decorador adicional).types.BuiltinFunctionType
também é o tipo de métodos internos ("normais") , que você provavelmente não deseja permitir, se não estiver seguindo ocallable
caminho.Desde o Python 2.1, você pode importar
isfunction
doinspect
módulo.fonte
open
ehasattr
.inspect.isfunction
documentação: "Return true se o objeto for uma função definida pelo usuário".A resposta aceita foi no momento em que foi oferecida, considerada correta. Como se vê, há nenhum substituto para
callable()
, que está de volta em Python 3.2: Especificamente,callable()
verifica otp_call
campo do objecto a ser testado. Não existe um equivalente simples em Python. A maioria dos testes sugeridos está correta na maioria das vezes:Podemos jogar uma chave de macaco nisso removendo o
__call__
da classe. E apenas para manter as coisas ainda mais emocionantes, adicione uma farsa__call__
à instância!Observe que isso realmente não é exigível:
callable()
retorna o resultado correto:Mas
hasattr
está errado :can_o_spam
afinal tem esse atributo; simplesmente não é usado ao chamar a instância.Ainda mais sutil,
isinstance()
também se engana:Como usamos essa verificação anteriormente e depois excluímos o método,
abc.ABCMeta
o resultado é armazenado em cache. Indiscutivelmente, isso é um bugabc.ABCMeta
. Dito isso, não há realmente nenhuma maneira possível de produzir um resultado mais preciso do que o resultado do que usarcallable()
ele próprio, já que otypeobject->tp_call
método do slot não é acessível de nenhuma outra maneira.Apenas use
callable()
fonte
hasattr(o, '__call__')
abordagem e por quecallable()
, se disponível, é superior.O seguinte deve retornar um booleano:
fonte
A ferramenta 2to3 do Python ( http://docs.python.org/dev/library/2to3.html ) sugere:
Parece que foi escolhido em vez do
hasattr(x, '__call__')
método por causa de http://bugs.python.org/issue7006 .fonte
callable()
para py3.3: bugs.python.org/issue10518#msg122309callable(x)
irá retornar true se o objeto passado pode ser chamado em Python, mas a função não existe no Python 3.0, e propriamente falando não vai distinguir entre:Você obterá
<class 'A'> True
e<type function> True
como saída.isinstance
funciona perfeitamente bem para determinar se algo é uma função (tentativaisinstance(b, types.FunctionType)
); se você estiver realmente interessado em saber se algo pode ser chamado, você pode usarhasattr(b, '__call__')
ou apenas tentar.Isso, é claro, não informará se é possível chamar, mas lança um
TypeError
quando é executado ou se não é chamado em primeiro lugar. Isso pode não lhe interessar.fonte
Se você deseja detectar tudo o que sintaticamente se parece com uma função: uma função, método, diversão / metanfetamina incorporada, lambda ... mas exclui objetos que podem ser chamados (objetos com
__call__
método definido), tente o seguinte:Comparei isso com o código de
is*()
verificações noinspect
módulo e a expressão acima é muito mais completa, especialmente se seu objetivo é filtrar quaisquer funções ou detectar propriedades regulares de um objeto.fonte
types
módulo. Eu estava testando umamake_stemmer()
fábrica que, às vezes, retornava uma função e, às vezes, umaStemmer
instância solicitável , e precisava detectar a diferença.Tente usar
callable(x)
.fonte
Se você aprendeu
C++
, deve estar familiarizado comfunction object
oufunctor
significa qualquer objeto que possabe called as if it is a function
.Em C ++,
an ordinary function
é um objeto de função, assim como um ponteiro de função; de maneira mais geral, também é um objeto de uma classe que defineoperator()
. Em C ++ 11 e superior,the lambda expression
é ofunctor
também.Semelhança, em Python, essas
functors
são todascallable
.An ordinary function
pode ser chamado,a lambda expression
pode ser chamado, umfunctional.partial
pode ser chamado, as instâncias declass with a __call__() method
podem ser chamadas.Ok, volte à pergunta:
I have a variable, x, and I want to know whether it is pointing to a function or not.
Então eu faço um experimento usando esses códigos:
Eu desenho uma tabela de tipos de functor que podem ser chamados usando os dados.
tal como:
fonte
Como resposta aceita, John Feminella afirmou que:
Mesmo assim, existem duas bibliotecas para distinguir estritamente as funções, eu desenho uma tabela comparável exaustiva:
8.9 types - Criação e nomes dinâmicos de tipos para tipos internos - documentação do Python 3.7.0
30.13 inspecionar - Inspecionar objetos dinâmicos - documentação do Python 3.7.0
A "digitação de pato" é uma solução preferida para uso geral:
Quanto à função builtins
Quando avançar mais uma etapa para verificar se a função interna ou a função definida pelo usuário
Determine se
builtin function
Sumário
Empregar
callable
para verificar o tipo de função,Use
types.BuiltinFunctionType
se você tiver uma demanda especificada.fonte
Uma função é apenas uma classe com um
__call__
método, então você pode fazerPor exemplo:
Essa é a "melhor" maneira de fazer isso, mas dependendo de por que você precisa saber se é possível chamar ou anotar, basta colocá-lo em um bloco try / execpt:
É discutível se try / except é mais Python do que fazer
if hasattr(x, '__call__'): x()
.. Eu diria quehasattr
é mais preciso, já que você não pega acidentalmente o TypeError errado, por exemplo:fonte
Aqui estão algumas outras maneiras:
Aqui está como eu criei o segundo:
fonte
Em vez de verificar para
'__call__'
(que não é exclusivo de funções), você pode verificar se uma função definida pelo usuário tem atributosfunc_name
,func_doc
etc. Isso não funciona para métodos.Outra maneira de verificar é usar o
isfunction()
método doinspect
módulo.Para verificar se um objeto é um método, use
inspect.ismethod()
fonte
Como as classes também têm
__call__
método, recomendo outra solução:fonte
hasattr(obj, '__call__')
é ambígua.Observe que as classes Python também são chamadas.
Para obter funções (e por funções queremos dizer funções padrão e lambdas) use:
fonte
Qualquer que seja a função que seja uma classe, é possível pegar o nome da classe da instância x e comparar:
fonte
As soluções usadas
hasattr(obj, '__call__')
ecallable(.)
mencionadas em algumas das respostas têm uma desvantagem principal: ambas também retornamTrue
para classes e instâncias de classes com um__call__()
método. Por exemplo.Uma maneira adequada de verificar se um objeto é uma função definida pelo usuário (e nada além disso) é usar
isfunction(.)
:Se você precisar procurar outros tipos, dê uma olhada em Inspecionar - Inspecionar objetos ativos .
fonte
Um verificador exato de funções
callable é uma solução muito boa. No entanto, eu queria tratar isso da maneira oposta a John Feminella. Em vez de tratá-lo dessa maneira:
Vamos tratar assim:
Como o Implementaríamos
O módulo 'tipos' possui muitas classes para detectar funções, sendo as mais úteis tipos. , mas também existem muitas outras, como um tipo de método, um tipo incorporado e um tipo lambda. Também consideraremos um objeto 'functools.partial' como uma função.
A maneira simples de verificar se é uma função é usando uma condição isinstance em todos esses tipos. Anteriormente, eu queria criar uma classe base que herda todas as opções acima, mas não consigo fazer isso, pois o Python não nos permite herdar algumas das classes acima.
Aqui está uma tabela de quais classes podem classificar quais funções:
Tabela de funções acima por kinght- 金
O código que faz isso
Agora, este é o código que faz todo o trabalho que descrevemos acima.
A única falsa foi is_function (parcial), porque essa é uma classe, não uma função, e isso é exatamente funções, não classes. Aqui está uma prévia para você experimentar o código.
Conclusão
callable (obj) é o método preferido para verificar se um objeto é uma função se você deseja digitar o pato sobre absolutos .
Nossa função is_function (obj) personalizada , talvez com algumas edições, seja o método preferido para verificar se um objeto é uma função, se você não conta uma instância de classe que pode ser chamada como uma função, mas apenas funções definidas internas ou com lambda , def ou parcial .
E acho que isso encerra tudo. Tenha um bom dia!
fonte
No Python3, eu vim com o
type (f) == type (lambda x:x)
que produzTrue
sef
é uma função eFalse
se não é. Mas acho que prefiroisinstance (f, types.FunctionType)
, o que parece menos ad hoc. Eu queria fazertype (f) is function
, mas isso não funciona.fonte
Após respostas anteriores, eu vim com isso:
fonte
Você pode tentar o seguinte:
ou até algo mais bizarro:
fonte
Se o código continuar a executar a chamada se o valor for exigível, basta realizar a chamada e capturar
TypeError
.fonte
x
tem.A seguir, é uma "maneira reprovada" de verificar. Também funciona com lambda.
fonte
Isso funciona para mim:
fonte
"<type 'function'>"
, por um número inteiro, eu fico"<type 'int'>"
, então eu não vejo como ele está funcionando para você: /open
ser considerado uma função?str(type(open))
dá<class 'builtin_function_or_method'>
em Python 3.