Como detecto se uma variável Python é uma função?


686

Eu tenho uma variável, xe 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'>

37
Estou deprimido com o número de respostas que trabalham em torno do problema, procurando por alguma chamada atributo ou função que pode ser chamado ... Uma maneira limpa é sobre o tipo (a) == types.functionType como sugerido por @ Ryan
Aster

44
@AsTeR A maneira correta de verificar as propriedades de objetos do tipo pato é perguntar se eles grasnam, não para ver se eles se encaixam em um contêiner do tamanho de um pato. A abordagem "compare diretamente" fornecerá a resposta errada para muitas funções, como builtins.
John Junella

3
@JohnFeminella Embora eu concorde com você em princípio. O OP não perguntou se era possível chamar, apenas se é uma função. Talvez se possa argumentar que ele precisava de uma distinção entre, por exemplo, funções e classes?
McKay

3
Para meus propósitos, eu vim aqui porque queria usar insepct.getsourceem 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__ou callable.
tsbertalan

4
@AsTeR É types.FunctionType, com maiúsculas F.
Ben Mares

Respostas:


891

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:

callable(obj)

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:

hasattr(obj, '__call__')

A types.FunctionTypesabordagem frequentemente sugerida não está correta porque falha em cobrir muitos casos que você provavelmente gostaria que ela passasse, como acontece com os builtins:

>>> isinstance(open, types.FunctionType)
False

>>> callable(open)
True

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.FunctionTypemenos que tenha uma idéia muito específica do que é uma função.


73
Isso também não dirá se é uma função - apenas se puder ser chamada.
Chris B.

23
Depende da aplicação se a distinção importa ou não; Eu suspeito que você esteja certo que isso não acontece com a pergunta original, mas isso está longe de ser certo.
Chris B.

5
As classes podem ter uma função de chamada anexada a ela. Portanto, esse definitivamente não é um bom método para distinguir. O método de Ryan é melhor.
Brian Bruggeman

43
o conceito de "digitação de pato" torna essa a melhor resposta, por exemplo, "o que importa se for uma função desde que se comporte como uma?"
jcomeau_ictx

8
Existem casos em que a distinção entre uma função que pode ser chamada e uma função é crucial, por exemplo, ao escrever um decorador (veja meu comentário na resposta de Ryan).
precisa

267

Tipos internos que não têm construtores no espaço de nomes interno (por exemplo, funções, geradores, métodos) estão no typesmódulo. Você pode usar types.FunctionTypeem uma isinstancechamada:

In [1]: import types
In [2]: types.FunctionType
Out[2]: <type 'function'>
In [3]: def f(): pass
   ...:
In [4]: isinstance(f, types.FunctionType)
Out[4]: True
In [5]: isinstance(lambda x : None, types.FunctionType)
Out[5]: True

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):

>>> type(zip), isinstance(zip, types.FunctionType)
(<class 'type'>, False)

open (as funções incorporadas têm um tipo diferente):

>>> type(open), isinstance(open, types.FunctionType)
(<class 'builtin_function_or_method'>, False)

e random.shuffle(tecnicamente, um método de uma random.Randominstância oculta ):

>>> type(random.shuffle), isinstance(random.shuffle, types.FunctionType)
(<class 'method'>, False)

Se você estiver fazendo algo específico para types.FunctionTypeinstâncias, como descompilar seu bytecode ou inspecionar variáveis ​​de fechamento, use types.FunctionType, mas se você precisar apenas de um objeto que possa ser chamado como uma função, use callable.


5
+1 respondendo à pergunta. No entanto, tentar adivinhar se um objeto é uma função - ou mesmo se é um objeto que pode ser chamado - geralmente é um erro. Sem mais informações do OP é difícil rejeitá-lo fora de mão, é claro, mas ainda assim ...
bobince

47
Na verdade, ele retornará False para funções internas, como 'open', por exemplo. Portanto, para ser específico, você terá que usar isinstance (f, (types.FunctionType, types.BuiltinFunctionType)). E, é claro, se você deseja estritamente apenas funções, não chamadas ou métodos.
Lukasz Korzybski

5
@ ŁukaszKorzybski e para ser mais preciso ... você também deve procurar functools.partial: isinstance(f, (types.FunctionType, types.BuiltinFunctionType, functools.partial))ou verificar f.funcnesse caso.
estani

3
@ Bobince, que tal este caso de usuário: eu quero escrever um decorador @fooque eu possa usar como @fooe 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).
precisa

types.BuiltinFunctionTypetambém é o tipo de métodos internos ("normais") , que você provavelmente não deseja permitir, se não estiver seguindo o callablecaminho.
User2357112 suporta Monica

92

Desde o Python 2.1, você pode importar isfunctiondo inspectmódulo.

>>> from inspect import isfunction
>>> def f(): pass
>>> isfunction(f)
True
>>> isfunction(lambda x: x)
True

3
Bom, mas parece retornar False para funções internas como opene hasattr.
Zecc

12
@Zecc isbuiltin é para isso.
Paolo

13
Consulte a inspect.isfunctiondocumentação: "Return true se o objeto for uma função definida pelo usuário".
Mark Mikofski

4
Observe que 'isfunction' não reconhece funções functool.partial.
Ishmael

74

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 o tp_callcampo do objecto a ser testado. Não existe um equivalente simples em Python. A maioria dos testes sugeridos está correta na maioria das vezes:

>>> class Spam(object):
...     def __call__(self):
...         return 'OK'
>>> can_o_spam = Spam()


>>> can_o_spam()
'OK'
>>> callable(can_o_spam)
True
>>> hasattr(can_o_spam, '__call__')
True
>>> import collections
>>> isinstance(can_o_spam, collections.Callable)
True

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!

>>> del Spam.__call__
>>> can_o_spam.__call__ = lambda *args: 'OK?'

Observe que isso realmente não é exigível:

>>> can_o_spam()
Traceback (most recent call last):
  ...
TypeError: 'Spam' object is not callable

callable() retorna o resultado correto:

>>> callable(can_o_spam)
False

Mas hasattrestá errado :

>>> hasattr(can_o_spam, '__call__')
True

can_o_spamafinal tem esse atributo; simplesmente não é usado ao chamar a instância.

Ainda mais sutil, isinstance()também se engana:

>>> isinstance(can_o_spam, collections.Callable)
True

Como usamos essa verificação anteriormente e depois excluímos o método, abc.ABCMeta o resultado é armazenado em cache. Indiscutivelmente, isso é um bug abc.ABCMeta. Dito isso, não há realmente nenhuma maneira possível de produzir um resultado mais preciso do que o resultado do que usar callable()ele próprio, já que o typeobject->tp_call método do slot não é acessível de nenhuma outra maneira.

Apenas use callable()


5
Ilustração surpreendente das armadilhas da hasattr(o, '__call__')abordagem e por que callable(), se disponível, é superior.
MestreLion

39

O seguinte deve retornar um booleano:

callable(x)

1
Isso resolve seu problema, mas ele ainda criou um mistério: se x é da 'função' da classe no módulo embutido e a ajuda (x .__ class__) descreve a "função da classe", por que a "função" aparentemente "não está definida"?
Ken

1
"function" não é uma palavra-chave ou um tipo interno. O tipo de funções é definida no módulo "tipos", como "types.FunctionType"
Chris B.


19

callable(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:

class A(object):
    def __call__(self):
        return 'Foo'

def B():
    return 'Bar'

a = A()
b = B

print type(a), callable(a)
print type(b), callable(b)

Você obterá <class 'A'> Truee <type function> Truecomo saída.

isinstancefunciona perfeitamente bem para determinar se algo é uma função (tentativa isinstance(b, types.FunctionType)); se você estiver realmente interessado em saber se algo pode ser chamado, você pode usar hasattr(b, '__call__')ou apenas tentar.

test_as_func = True
try:
    b()
except TypeError:
    test_as_func = False
except:
    pass

Isso, é claro, não informará se é possível chamar, mas lança um TypeErrorquando é executado ou se não é chamado em primeiro lugar. Isso pode não lhe interessar.


8
Chamá-lo é uma má ideia. E se tiver efeitos colaterais, ou realmente fizer alguma coisa, mas levar um tempo muito longo?
Asmeurer # 15/13

@asmeurer - Por que mais você precisaria saber se é uma função se você não está chamando?
detly

1
@detly: para depuração, eu regularmente quero imprimir todas as variáveis ​​em um objeto, os métodos geralmente não são úteis para mim, então eu não gostaria de executá-los. No final, eu apenas listar todas as propriedades não pode ser chamado com os valores correspondentes :)
Wolph

2
Só porque você não está ligando, isso não significa que não está sendo chamado. Talvez você esteja fazendo despachos.
asmeurer

4
Há um grande problema com o uso de exceções para saber se é possível chamar ou não; e se for possível chamar, mas chamá-lo gera uma exceção que você está procurando? Os dois ignoram silenciosamente um erro e diagnosticam incorretamente se é possível chamar. Quando você está usando o EAFP, você realmente deseja evitar tentar demais, mas não há como fazer isso neste caso de uso.
Ben

15

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:

import types
isinstance(x, (types.FunctionType, types.BuiltinFunctionType, types.MethodType, types.BuiltinMethodType, types.UnboundMethodType))

Comparei isso com o código de is*()verificações no inspectmódulo e a expressão acima é muito mais completa, especialmente se seu objetivo é filtrar quaisquer funções ou detectar propriedades regulares de um objeto.


Obrigado por me indicar o typesmódulo. Eu estava testando uma make_stemmer()fábrica que, às vezes, retornava uma função e, às vezes, uma Stemmerinstância solicitável , e precisava detectar a diferença.
21416 hobs


6

Se você aprendeu C++, deve estar familiarizado com function objectou functorsignifica 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 define operator(). Em C ++ 11 e superior, the lambda expressioné ofunctor também.

Semelhança, em Python, essas functorssão todas callable. An ordinary functionpode ser chamado, a lambda expressionpode ser chamado, um functional.partialpode ser chamado, as instâncias de class with a __call__() methodpodem ser chamadas.


Ok, volte à pergunta: I have a variable, x, and I want to know whether it is pointing to a function or not.

Se você deseja julgar o clima, o objeto age como uma função, então o callablemétodo sugerido por@John Feminella é ok.

Se você desejar judge whether a object is just an ordinary function or not(não uma instância de classe que possa ser chamada ou uma expressão lambda), o xtypes.XXXsugerido por @Ryané uma escolha melhor.

Então eu faço um experimento usando esses códigos:

#!/usr/bin/python3
# 2017.12.10 14:25:01 CST
# 2017.12.10 15:54:19 CST

import functools
import types
import pprint

Defina uma classe e uma função comum.

class A():
    def __call__(self, a,b):
        print(a,b)
    def func1(self, a, b):
        print("[classfunction]:", a, b)
    @classmethod
    def func2(cls, a,b):
        print("[classmethod]:", a, b)
    @staticmethod
    def func3(a,b):
        print("[staticmethod]:", a, b)

def func(a,b):
    print("[function]", a,b)

Defina os functores:

#(1.1) built-in function
builtins_func = open
#(1.2) ordinary function
ordinary_func = func
#(1.3) lambda expression
lambda_func  = lambda a : func(a,4)
#(1.4) functools.partial
partial_func = functools.partial(func, b=4)

#(2.1) callable class instance
class_callable_instance = A()
#(2.2) ordinary class function
class_ordinary_func = A.func1
#(2.3) bound class method
class_bound_method = A.func2
#(2.4) static class method
class_static_func = A.func3

Defina a lista de functores e a lista de tipos:

## list of functors
xfuncs = [builtins_func, ordinary_func, lambda_func, partial_func, class_callable_instance, class_ordinary_func, class_bound_method, class_static_func]
## list of type
xtypes = [types.BuiltinFunctionType, types.FunctionType, types.MethodType, types.LambdaType, functools.partial]

Julgue se o functor é exigível. Como você pode ver, todos eles são chamados.

res = [callable(xfunc)  for xfunc in xfuncs]
print("functors callable:")
print(res)

"""
functors callable:
[True, True, True, True, True, True, True, True]
"""

Julgue o tipo do functor (types.XXX). Então os tipos de functores não são todos iguais.

res = [[isinstance(xfunc, xtype) for xtype in xtypes] for xfunc in xfuncs]

## output the result
print("functors' types")
for (row, xfunc) in zip(res, xfuncs):
    print(row, xfunc)

"""
functors' types
[True, False, False, False, False] <built-in function open>
[False, True, False, True, False] <function func at 0x7f1b5203e048>
[False, True, False, True, False] <function <lambda> at 0x7f1b5081fd08>
[False, False, False, False, True] functools.partial(<function func at 0x7f1b5203e048>, b=4)
[False, False, False, False, False] <__main__.A object at 0x7f1b50870cc0>
[False, True, False, True, False] <function A.func1 at 0x7f1b5081fb70>
[False, False, True, False, False] <bound method A.func2 of <class '__main__.A'>>
[False, True, False, True, False] <function A.func3 at 0x7f1b5081fc80>
"""

Eu desenho uma tabela de tipos de functor que podem ser chamados usando os dados.

insira a descrição da imagem aqui

Depois, você pode escolher os tipos de functores adequados.

tal como:

def func(a,b):
    print("[function]", a,b)

>>> callable(func)
True
>>> isinstance(func,  types.FunctionType)
True
>>> isinstance(func, (types.BuiltinFunctionType, types.FunctionType, functools.partial))
True
>>> 
>>> isinstance(func, (types.MethodType, functools.partial))
False

6

Como resposta aceita, John Feminella afirmou que:

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. A abordagem "compare diretamente" fornecerá a resposta errada para muitas funções, como builtins.

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

#import inspect             #import types
['isabstract',
 'isasyncgen',              'AsyncGeneratorType',
 'isasyncgenfunction', 
 'isawaitable',
 'isbuiltin',               'BuiltinFunctionType',
                            'BuiltinMethodType',
 'isclass',
 'iscode',                  'CodeType',
 'iscoroutine',             'CoroutineType',
 'iscoroutinefunction',
 'isdatadescriptor',
 'isframe',                 'FrameType',
 'isfunction',              'FunctionType',
                            'LambdaType',
                            'MethodType',
 'isgenerator',             'GeneratorType',
 'isgeneratorfunction',
 'ismethod',
 'ismethoddescriptor',
 'ismodule',                'ModuleType',        
 'isroutine',            
 'istraceback',             'TracebackType'
                            'MappingProxyType',
]

A "digitação de pato" é uma solução preferida para uso geral:

def detect_function(obj):
    return hasattr(obj,"__call__")

In [26]: detect_function(detect_function)
Out[26]: True
In [27]: callable(detect_function)
Out[27]: True

Quanto à função builtins

In [43]: callable(hasattr)
Out[43]: True

Quando avançar mais uma etapa para verificar se a função interna ou a função definida pelo usuário

#check inspect.isfunction and type.FunctionType
In [46]: inspect.isfunction(detect_function)
Out[46]: True
In [47]: inspect.isfunction(hasattr)
Out[47]: False
In [48]: isinstance(detect_function, types.FunctionType)
Out[48]: True
In [49]: isinstance(getattr, types.FunctionType)
Out[49]: False
#so they both just applied to judge the user-definded

Determine se builtin function

In [50]: isinstance(getattr, types.BuiltinFunctionType)
Out[50]: True
In [51]: isinstance(detect_function, types.BuiltinFunctionType)
Out[51]: False

Sumário

Empregar callablepara verificar o tipo de função,
Use types.BuiltinFunctionTypese você tiver uma demanda especificada.


5

Uma função é apenas uma classe com um __call__método, então você pode fazer

hasattr(obj, '__call__')

Por exemplo:

>>> hasattr(x, '__call__')
True

>>> x = 2
>>> hasattr(x, '__call__')
False

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:

try:
    x()
except TypeError:
    print "was not callable"

É discutível se try / except é mais Python do que fazer if hasattr(x, '__call__'): x().. Eu diria que hasattré mais preciso, já que você não pega acidentalmente o TypeError errado, por exemplo:

>>> def x():
...     raise TypeError
... 
>>> hasattr(x, '__call__')
True # Correct
>>> try:
...     x()
... except TypeError:
...     print "x was not callable"
... 
x was not callable # Wrong!

Use o tratamento de exceções para proteger apenas contra comportamentos inesperados, nunca para o fluxo lógico - isso definitivamente não é Pythonic.
gotgenes

Bem, o hasattr basicamente faz um getattr em um bloco try / except (embora em C). blog.jancewicz.net/2007/10/reflection-hasattr.html
dbr

@dbr: Mas o hasattr é mais estético.
9139 Nikhil Chelliah

5

Aqui estão algumas outras maneiras:

def isFunction1(f) :
    return type(f) == type(lambda x: x);

def isFunction2(f) :
    return 'function' in str(type(f));

Aqui está como eu criei o segundo:

>>> type(lambda x: x);
<type 'function'>
>>> str(type(lambda x: x));
"<type 'function'>"
# Look Maa, function! ... I ACTUALLY told my mom about this!

Isso é legal! Deve funcionar em todas as versões do python2.xe python3.x!
Saurav Kumar

4

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 atributos func_name, func_docetc. Isso não funciona para métodos.

>>> def x(): pass
... 
>>> hasattr(x, 'func_name')
True

Outra maneira de verificar é usar o isfunction()método do inspectmódulo.

>>> import inspect
>>> inspect.isfunction(x)
True

Para verificar se um objeto é um método, use inspect.ismethod()


4

Como as classes também têm __call__método, recomendo outra solução:

class A(object):
    def __init__(self):
        pass
    def __call__(self):
        print 'I am a Class'

MyClass = A()

def foo():
    pass

print hasattr(foo.__class__, 'func_name') # Returns True
print hasattr(A.__class__, 'func_name')   # Returns False as expected

print hasattr(foo, '__call__') # Returns True
print hasattr(A, '__call__')   # (!) Returns True while it is not a function

1
Concorde com a sua resposta, a resposta de John Feminella hasattr(obj, '__call__')é ambígua.
GoingMyWay

4

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:

import types

def is_func(obj):
    return isinstance(obj, (types.FunctionType, types.LambdaType))


def f(x):
    return x


assert is_func(f)
assert is_func(lambda x: x)

2

Qualquer que seja a função que seja uma classe, é possível pegar o nome da classe da instância x e comparar:


if(x.__class__.__name__ == 'function'):
     print "it's a function"

2

As soluções usadas hasattr(obj, '__call__')e callable(.)mencionadas em algumas das respostas têm uma desvantagem principal: ambas também retornam Truepara classes e instâncias de classes com um __call__()método. Por exemplo.

>>> import collections
>>> Test = collections.namedtuple('Test', [])
>>> callable(Test)
True
>>> hasattr(Test, '__call__')
True

Uma maneira adequada de verificar se um objeto é uma função definida pelo usuário (e nada além disso) é usar isfunction(.):

>>> import inspect
>>> inspect.isfunction(Test)
False
>>> def t(): pass
>>> inspect.isfunction(t)
True

Se você precisar procurar outros tipos, dê uma olhada em Inspecionar - Inspecionar objetos ativos .


2

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:

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. A abordagem "compare diretamente" fornecerá a resposta errada para muitas funções, como builtins.

Vamos tratar assim:

A maneira correta de verificar se algo é um pato não é ver se ele pode grasnar, mas sim se ele realmente é um pato através de vários filtros, em vez de apenas verificar se parece um pato da superfície.

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 de kinght- 金 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.

from types import BuiltinFunctionType, BuiltinMethodType,  FunctionType, MethodType, LambdaType
from functools import partial

def is_function(obj):
  return isinstance(obj, (BuiltinFunctionType, BuiltinMethodType,  FunctionType, MethodType, LambdaType, partial))

#-------------------------------------------------

def my_func():
  pass

def add_both(x, y):
  return x + y

class a:
  def b(self):
    pass

check = [

is_function(lambda x: x + x),
is_function(my_func),
is_function(a.b),
is_function(partial),
is_function(partial(add_both, 2))

]

print(check)
>>> [True, True, True, False, True]

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!


1

No Python3, eu vim com o type (f) == type (lambda x:x)que produz Truese fé uma função e Falsese não é. Mas acho que prefiro isinstance (f, types.FunctionType), o que parece menos ad hoc. Eu queria fazer type (f) is function, mas isso não funciona.


0

Após respostas anteriores, eu vim com isso:

from pprint import pprint

def print_callables_of(obj):
    li = []
    for name in dir(obj):
        attr = getattr(obj, name)
        if hasattr(attr, '__call__'):
            li.append(name)
    pprint(li)

0

Você pode tentar o seguinte:

if obj.__class__.__name__ in ['function', 'builtin_function_or_method']:
    print('probably a function')

ou até algo mais bizarro:

if "function" in lower(obj.__class__.__name__):
    print('probably a function')

-1

Se o código continuar a executar a chamada se o valor for exigível, basta realizar a chamada e capturar TypeError.

def myfunc(x):
  try:
    x()
  except TypeError:
    raise Exception("Not callable")

4
Isso é perigoso; você não tem idéia do que efeitos colaterais xtem.
precisa saber é o seguinte

-2

A seguir, é uma "maneira reprovada" de verificar. Também funciona com lambda.

def a():pass
type(a) #<class 'function'>
str(type(a))=="<class 'function'>" #True

b = lambda x:x*2
str(type(b))=="<class 'function'>" #True

-3

Isso funciona para mim:

str(type(a))=="<class 'function'>"

1
E o que isso nos diz se o resultado for uma string vazia? Para uma função, eu recebo "<type 'function'>", por um número inteiro, eu fico "<type 'int'>", então eu não vejo como ele está funcionando para você: /
pawamoy

Agora só funciona para Python 3 :) Também, dependendo da intenção original da pergunta, ela seria incompleta: o builtin deve openser considerado uma função? str(type(open))<class 'builtin_function_or_method'>em Python 3.
pawamoy
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.