Localizando quais métodos um objeto Python possui

430

Dado um objeto Python de qualquer tipo, existe uma maneira fácil de obter a lista de todos os métodos que esse objeto possui?

Ou,

se isso não for possível, existe pelo menos uma maneira fácil de verificar se ele possui um método específico, além de simplesmente verificar se ocorre um erro quando o método é chamado?

Thomas Lötzer
fonte
Relevante: stackoverflow.com/q/46033277/1959808
Ioannis Filippidis

Respostas:

524

Para muitos objetos , você pode usar esse código, substituindo 'object' pelo objeto em que está interessado:

object_methods = [method_name for method_name in dir(object)
                  if callable(getattr(object, method_name))]

Eu o descobri no diveintopython.net (agora arquivado). Felizmente, isso deve fornecer mais detalhes!

Se você receber um AttributeError, poderá usar isso :

getattr(é intolerante às subclasses virtuais abstratas do estilo pandas python3.6. Este código faz o mesmo que acima e ignora exceções.

import pandas as pd 
df = pd.DataFrame([[10, 20, 30], [100, 200, 300]],  
                  columns=['foo', 'bar', 'baz']) 
def get_methods(object, spacing=20): 
  methodList = [] 
  for method_name in dir(object): 
    try: 
        if callable(getattr(object, method_name)): 
            methodList.append(str(method_name)) 
    except: 
        methodList.append(str(method_name)) 
  processFunc = (lambda s: ' '.join(s.split())) or (lambda s: s) 
  for method in methodList: 
    try: 
        print(str(method.ljust(spacing)) + ' ' + 
              processFunc(str(getattr(object, method).__doc__)[0:90])) 
    except: 
        print(method.ljust(spacing) + ' ' + ' getattr() failed') 


get_methods(df['foo']) 
ljs
fonte
3
É uma compreensão de lista, retornando uma lista de métodos em que método é um item na lista retornada por dir (objeto) e onde cada método é adicionado à lista somente se getattr (objeto, método) retornar uma chamada.
Mnebuerquo
1
Como exatamente você usa isso? Para dizer, imprima uma lista dos métodos.
pântano
12
@marsh Para imprimir os métodos: print [method for method in dir(object) if callable(getattr(object, method))].
Orienteerix
1
Estou recebendo um AttributeError: module 'pandas.core.common' has no attribute 'AbstractMethodError'quando tento executar isso. Veja detalhes em stackoverflow.com/q/54713287/9677043 .
Karl Baker
1
não funciona para o objeto dataframe do pandas no python 3.6.
Stefan Karlsson
226

Você pode usar a dir()função interna para obter uma lista de todos os atributos que um módulo possui. Tente isso na linha de comando para ver como funciona.

>>> import moduleName
>>> dir(moduleName)

Além disso, você pode usar a hasattr(module_name, "attr_name")função para descobrir se um módulo possui um atributo específico.

Consulte o Guia de introspecção do Python para obter mais informações.

Bill the Lizard
fonte
hasattrajudou meu caso de uso a descobrir se o objeto python tem uma variável ou método de membro específico.
Akshay
Não sei por que essa solução não foi votada o suficiente. Isso é conciso e preciso.
Prasad Raghavendra
93

O método mais simples é usar dir(objectname). Ele exibirá todos os métodos disponíveis para esse objeto. Truque legal.

Pawan Kumar
fonte
3
Ele também exibe os atributos do objeto, portanto, se você deseja encontrar métodos especificamente, ele não funcionará.
9606 eric
Sim. Acordado. Mas não conheço nenhuma outra técnica para obter apenas a lista de métodos. Talvez a melhor idéia é fazer com que a lista de atributos e métodos e, em seguida, usar <hasattr (objeto "method_name"> para mais filtro para fora?
Pawan Kumar
1
@neuronet, estou tentando executar a resposta aceita, mas obtendo um AttributeError: module 'pandas.core.common' has no attribute 'AbstractMethodError'. Alguma ideia? Consulte deets em stackoverflow.com/q/54713287/9677043 . +1 para @Pawan Kumar b / c, a resposta funciona e para @ljs, pela promessa de uma lista filtrada apenas dos métodos.
Karl Baker
30

Para verificar se ele possui um método específico:

hasattr(object,"method")
Bill the Lizard
fonte
14
como o OP está procurando um método e não apenas um atributo, acho que você quer ir além:if hasattr(obj,method) and callable(getattr(obj,method)):
Bruno Bronosky
28

Eu acredito que o que você quer é algo como isto:

uma lista de atributos de um objeto

Na minha humilde opinião, a função interna dir()pode fazer esse trabalho por você. Retirado da help(dir)saída do seu Python Shell:

dir (...)

dir([object]) -> list of strings

Se chamado sem um argumento, retorne os nomes no escopo atual.

Senão, retorne uma lista alfabética de nomes que compreendem (alguns) os atributos do objeto especificado e os atributos acessíveis a partir dele.

Se o objeto fornecer um método nomeado __dir__, ele será usado; caso contrário, a lógica dir () padrão será usada e retornará:

  • para um objeto de módulo: os atributos do módulo.
  • para um objeto de classe: seus atributos e recursivamente os atributos de suas bases.
  • para qualquer outro objeto: seus atributos, atributos de sua classe e recursivamente os atributos das classes base de sua classe.

Por exemplo:

$ python
Python 2.7.6 (default, Jun 22 2015, 17:58:13) 
[GCC 4.8.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.

>>> a = "I am a string"
>>>
>>> type(a)
<class 'str'>
>>>
>>> dir(a)
['__add__', '__class__', '__contains__', '__delattr__', '__doc__',
'__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__',
'__getnewargs__', '__getslice__', '__gt__', '__hash__', '__init__',
'__le__', '__len__', '__lt__', '__mod__', '__mul__', '__ne__', '__new__',
'__reduce__', '__reduce_ex__', '__repr__', '__rmod__', '__rmul__',
'__setattr__', '__sizeof__', '__str__', '__subclasshook__',
'_formatter_field_name_split', '_formatter_parser', 'capitalize',
'center', 'count', 'decode', 'encode', 'endswith', 'expandtabs', 'find',
'format', 'index', 'isalnum', 'isalpha', 'isdigit', 'islower', 'isspace',
'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'partition',
'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip',
'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title',
'translate', 'upper', 'zfill']

Enquanto eu checava seu problema, decidi demonstrar minha linha de pensamento, com uma melhor formatação da saída de dir().

dir_attributes.py (Python 2.7.6)

#!/usr/bin/python
""" Demonstrates the usage of dir(), with better output. """

__author__ = "ivanleoncz"

obj = "I am a string."
count = 0

print "\nObject Data: %s" % obj
print "Object Type: %s\n" % type(obj)

for method in dir(obj):
    # the comma at the end of the print, makes it printing 
    # in the same line, 4 times (count)
    print "| {0: <20}".format(method),
    count += 1
    if count == 4:
        count = 0
        print

dir_attributes.py (Python 3.4.3)

#!/usr/bin/python3
""" Demonstrates the usage of dir(), with better output. """

__author__ = "ivanleoncz"

obj = "I am a string."
count = 0

print("\nObject Data: ", obj)
print("Object Type: ", type(obj),"\n")

for method in dir(obj):
    # the end=" " at the end of the print statement, 
    # makes it printing in the same line, 4 times (count)
    print("|    {:20}".format(method), end=" ")
    count += 1
    if count == 4:
        count = 0
        print("")

Espero que eu tenha contribuído :).

ivanleoncz
fonte
1
Contribuído? Sua resposta funcionou para mim no Python 2.7.12, então sim!
Gsamaras #
23

Além das respostas mais diretas, seria negligente se não mencionasse o iPython . Pressione 'tab' para ver os métodos disponíveis, com preenchimento automático.

E depois de encontrar um método, tente:

help(object.method) 

para ver os pydocs, a assinatura do método etc.

Ahh ... REPL .

jmanning2k
fonte
12

Se você deseja métodos especificamente , deve usar o inspect.ismethod .

Para nomes de métodos:

import inspect
method_names = [attr for attr in dir(self) if inspect.ismethod(getattr(self, attr))]

Para os próprios métodos:

import inspect
methods = [member for member in [getattr(self, attr) for attr in dir(self)] if inspect.ismethod(member)]

Às vezes, também inspect.isroutinepode ser útil (para embutidos, extensões C, Cython sem a diretiva de compilação "binding").

paulmelnikow
fonte
Você não deveria usar em inspect.getmembersvez de usar direm uma lista de compreensão?
Boris
Sim, isso parece melhor!
paulmelnikow 24/04
11

Abra o shell bash (ctrl + alt + T no Ubuntu). Inicie o shell python3 nele. Crie um objeto para observar métodos de. Basta adicionar um ponto depois e pressionar duas vezes "tab" e você verá algo assim:

 user@note:~$ python3
 Python 3.4.3 (default, Nov 17 2016, 01:08:31) 
 [GCC 4.8.4] on linux
 Type "help", "copyright", "credits" or "license" for more information.
 >>> import readline
 >>> readline.parse_and_bind("tab: complete")
 >>> s = "Any object. Now it's a string"
 >>> s. # here tab should be pressed twice
 s.__add__(           s.__rmod__(          s.istitle(
 s.__class__(         s.__rmul__(          s.isupper(
 s.__contains__(      s.__setattr__(       s.join(
 s.__delattr__(       s.__sizeof__(        s.ljust(
 s.__dir__(           s.__str__(           s.lower(
 s.__doc__            s.__subclasshook__(  s.lstrip(
 s.__eq__(            s.capitalize(        s.maketrans(
 s.__format__(        s.casefold(          s.partition(
 s.__ge__(            s.center(            s.replace(
 s.__getattribute__(  s.count(             s.rfind(
 s.__getitem__(       s.encode(            s.rindex(
 s.__getnewargs__(    s.endswith(          s.rjust(
 s.__gt__(            s.expandtabs(        s.rpartition(
 s.__hash__(          s.find(              s.rsplit(
 s.__init__(          s.format(            s.rstrip(
 s.__iter__(          s.format_map(        s.split(
 s.__le__(            s.index(             s.splitlines(
 s.__len__(           s.isalnum(           s.startswith(
 s.__lt__(            s.isalpha(           s.strip(
 s.__mod__(           s.isdecimal(         s.swapcase(
 s.__mul__(           s.isdigit(           s.title(
 s.__ne__(            s.isidentifier(      s.translate(
 s.__new__(           s.islower(           s.upper(
 s.__reduce__(        s.isnumeric(         s.zfill(
 s.__reduce_ex__(     s.isprintable(       
 s.__repr__(          s.isspace(           
Valery Ramusik
fonte
1
Enquanto falamos sobre soluções alternativas como essa, adicionarei que você também pode executar ipython, começar a digitar o objeto e pressionar tabe ele também funcionará. Nenhuma configuração de linha de leitura necessária
Max Coplan
1
@MaxCoplan Eu adicionei a solução em código para os casos em guia-conclusão não está habilitado por padrão
Valery Ramusik
8

O problema com todos os métodos indicados aqui é que você NÃO pode ter certeza de que não existe um método.

No Python, você pode interceptar a chamada de ponto __getattr__e __getattribute__, possibilitando a criação do método "em tempo de execução"

Exemplo:

class MoreMethod(object):
    def some_method(self, x):
        return x
    def __getattr__(self, *args):
        return lambda x: x*2

Se você executá-lo, poderá chamar o método inexistente no dicionário de objetos ...

>>> o = MoreMethod()
>>> o.some_method(5)
5
>>> dir(o)
['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattr__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'some_method']
>>> o.i_dont_care_of_the_name(5)
10

E é por isso que você usa o Easy para pedir perdão do que os paradigmas de permissão no Python.

Cld
fonte
6

A maneira mais simples de obter a lista de métodos de qualquer objeto é usar o help()comando

%help(object)

Ele listará todos os métodos disponíveis / importantes associados a esse objeto.

Por exemplo:

help(str)
Paritosh Vyas
fonte
O que %faz no primeiro exemplo? Não funciona no meu Python 2.7.
Scorchio
@ Scorchio Eu usei "%" como prompt em vez de ">>>" para python. Você pode retirar% antes de executar o comando.
Paritosh Vyas
3
import moduleName
for x in dir(moduleName):
print(x)

Isso deve funcionar :)

A máfia
fonte
1

Pode-se criar uma getAttrsfunção que retornará os nomes de propriedades que podem ser chamados de um objeto

def getAttrs(object):
  return filter(lambda m: callable(getattr(object, m)), dir(object))

print getAttrs('Foo bar'.split(' '))

Isso voltaria

['__add__', '__class__', '__contains__', '__delattr__', '__delitem__',
 '__delslice__', '__eq__', '__format__', '__ge__', '__getattribute__', 
 '__getitem__', '__getslice__', '__gt__', '__iadd__', '__imul__', '__init__', 
 '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', 
 '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', 
 '__setattr__', '__setitem__', '__setslice__', '__sizeof__', '__str__', 
 '__subclasshook__', 'append', 'count', 'extend', 'index', 'insert', 'pop', 
 'remove', 'reverse', 'sort']
james_womack
fonte
1

Não há uma maneira confiável de listar todos os métodos do objeto. dir(object)geralmente é útil, mas em alguns casos pode não listar todos os métodos. De acordo com a dir()documentação : "Com um argumento, tente retornar uma lista de atributos válidos para esse objeto."

A verificação de que o método existe pode ser feita callable(getattr(object, method))como já mencionado lá.

aver
fonte
1

Pegue uma lista como um objeto

obj = []

list(filter(lambda x:callable(getattr(obj,x)),obj.__dir__()))

Você obtém:

['__add__',
 '__class__',
 '__contains__',
 '__delattr__',
 '__delitem__',
 '__dir__',
 '__eq__',
 '__format__',
 '__ge__',
 '__getattribute__',
 '__getitem__',
 '__gt__',
 '__iadd__',
 '__imul__',
 '__init__',
 '__init_subclass__',
 '__iter__',
 '__le__',
 '__len__',
 '__lt__',
 '__mul__',
 '__ne__',
 '__new__',
 '__reduce__',
 '__reduce_ex__',
 '__repr__',
 '__reversed__',
 '__rmul__',
 '__setattr__',
 '__setitem__',
 '__sizeof__',
 '__str__',
 '__subclasshook__',
 'append',
 'clear',
 'copy',
 'count',
 'extend',
 'index',
 'insert',
 'pop',
 'remove',
 'reverse',
 'sort']
Mahdi Ghelichi
fonte
0

... existe pelo menos uma maneira fácil de verificar se ele possui um método específico, além de simplesmente verificar se ocorre um erro quando o método é chamado

Embora " Mais fácil pedir perdão do que permissão " seja certamente o caminho pitônico, o que você está procurando talvez:

d={'foo':'bar', 'spam':'eggs'}
if 'get' in dir(d):
    d.get('foo')
# OUT: 'bar'
Bruno Bronosky
fonte
0

Para procurar um método específico em um módulo inteiro

for method in dir(module) :
  if "keyword_of_methode" in method :
   print(method, end="\n")
Simon PII
fonte
-1

Se você estiver, por exemplo, usando shell plus, poderá usar isso:

>> MyObject??

dessa forma, com o '??' logo após o seu objeto, ele mostrará todos os atributos / métodos que a classe possui.

Nick Cuevas
fonte