Пошук методів, якими володіє об’єкт Python


427

З огляду на будь-який тип об’єкта Python, чи є простий спосіб отримати список усіх методів, якими володіє цей об’єкт?

Або,

якщо це неможливо, чи є принаймні простий спосіб перевірити, чи є у нього певний метод, крім простої перевірки, чи виникає помилка при виклику методу?


Відповіді:


522

Для багатьох об'єктів ви можете використовувати цей код, замінивши "об'єкт" об'єктом, який вас цікавить:

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

Я виявив це на diveintopython.net (зараз архівовано). Будемо сподіватися, що це має надати ще деякі деталі!

Якщо ви отримаєте AttributeError, ви можете використовувати це замість цього :

getattr(є нетерпимим до панд стилів python3.6 абстрактних віртуальних підкласів. Цей код робить те саме, що вище, і ігнорує винятки.

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']) 

3
Це розуміння списку, повернення списку методів, де метод є елементом у списку, поверненим dir (об'єктом), і коли кожен метод додається до списку, лише якщо getattr (об'єкт, метод) повертає позивний.
Mnebuerquo

1
Як саме ти цим користуєшся? Скажімо, роздрукуйте список методів.
болото

12
@marsh Щоб друку методи: print [method for method in dir(object) if callable(getattr(object, method))].
Orienteerix

1
Я отримую, AttributeError: module 'pandas.core.common' has no attribute 'AbstractMethodError'коли я намагаюся запустити це. Детальну інформацію див. На сайті stackoverflow.com/q/54713287/9677043 .
Карл Бейкер

1
не працює для об'єкта фрейму даних pandas в python 3.6.
Стефан Карлссон

226

Ви можете використовувати вбудовану dir()функцію, щоб отримати список усіх атрибутів, які має модуль. Спробуйте це в командному рядку, щоб побачити, як це працює.

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

Також ви можете скористатися hasattr(module_name, "attr_name")функцією, щоб дізнатись, чи має модуль певний атрибут.

Для отримання додаткової інформації дивіться Посібник із самоаналізу Python .


hasattrдопоміг моєму використанню випадку виявити, чи є об'єкт python певною змінною або методом члена.
Акшай

Я не впевнений, чому це рішення недостатньо прихильне. Це лаконічно і точно.
Прасад Рагавендра

93

Найпростіший метод - це використовувати dir(objectname). Він відобразить усі методи, доступні для цього об’єкта. Класна хитрість.


2
Він також відображає атрибути об’єкта, тому якщо ви хочете спеціально знайти методи, він не вийде.
eric

Так. Домовились. Але я не знаю жодної іншої техніки, щоб отримати лише список методів. Можливо, найкраща ідея - отримати список і атрибутів, і методів, а потім використовувати <hasattr (object, "method_name"> для подальшого фільтрування?
Pawan Kumar

1
@neuronet, я намагаюся виконати прийняту відповідь, але отримую відповідь AttributeError: module 'pandas.core.common' has no attribute 'AbstractMethodError'. Будь-які ідеї? Дивіться декети на сайті stackoverflow.com/q/54713287/9677043 . +1 до @Pawan Kumar b / c відповідь працює, а @ljs за обіцянку відфільтрованого списку лише методів.
Карл Бейкер

30

Щоб перевірити, чи є у нього певний метод:

hasattr(object,"method")

14
оскільки ОП шукає метод, а не просто та атрибут, я думаю, ви хочете піти на крок далі:if hasattr(obj,method) and callable(getattr(obj,method)):
Бруно Броноський,

28

Я вважаю, що те, що ти хочеш, є приблизно таким:

список атрибутів від об’єкта

На мою скромну думку, вбудована функція dir()може зробити цю роботу за вас. Взяті з help(dir)результатів на вашому Python Shell:

реж. (...)

dir([object]) -> list of strings

Якщо викликано без аргументу, поверніть імена в поточну область.

В іншому випадку поверніть алфавітний список імен, що містять (деякі) атрибути даного об'єкта, і атрибути, доступні від нього.

Якщо об'єкт надає метод, названий __dir__, він буде використаний; інакше використовується логіка dir () за замовчуванням і повертає:

  • для об'єкта модуля: атрибути модуля.
  • для об’єкта класу: його атрибути та рекурсивно атрибути його баз.
  • для будь-якого іншого об'єкта: його атрибути, атрибути класу та рекурсивно атрибути базових класів класу.

Наприклад:

$ 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']

Перевіряючи ваше питання, я вирішив продемонструвати свій порядок думок з кращим форматуванням результатів 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("")

Сподіваюся, що я зробив свій внесок :).


1
Внесли свій внесок? Ваша відповідь працювала для мене в Python 2.7.12, так що так!
gsamaras

23

На додаток до більш прямих відповідей, я був би звільнений, якби не згадував про iPython . Натисніть "вкладку", щоб побачити доступні методи з автоматичним завершенням.

І знайшовши метод, спробуйте:

help(object.method) 

щоб побачити pydocs, підпис методу тощо.

Ааа ... ЗАПОВІДЬ .


12

Якщо ви конкретно хочете методів , вам слід скористатися методом inspect.ismethod .

Для назв методів:

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

Для самих методів:

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

Іноді inspect.isroutineможе бути корисним також (для вбудованих модулів, розширень C, Cython без директиви компілятора "прив'язування").


Ви не повинні використовувати inspect.getmembersзамість використання dirв розумінні списку?
Борис

Так, це здається краще!
paulmelnikow

11

Відкрита оболонка bash (ctrl + alt + T на Ubuntu). Запустіть в неї оболонку python3. Створіть об’єкт для спостереження за методами. Просто додайте крапку після цього і натисніть двічі "вкладку", і ви побачите щось подібне:

 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(           

1
Поки ми говоримо про обхідні шляхи, як це, я додам, що ви також можете запустити ipython, почніть вводити об'єкт і натисніть, tabі він також буде працювати. Не потрібні налаштування для
читання ліній

1
@MaxCoplan Я додав рішення у коді для випадків, коли заповнення вкладки за замовчуванням не ввімкнено
Валерій Рамусік

8

Проблема з усіма вказаними тут методами полягає в тому, що ви НЕ можете бути впевнені, що метод не існує.

В Python ви можете перехопити точку виклику через __getattr__та __getattribute__, що дозволяє створити метод «під час виконання»

Приклад:

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

Якщо ви виконаєте його, ви можете викликати метод, який не існує в словнику об'єктів ...

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

І саме тому ви використовуєте простіше, щоб просити пробачення, ніж парадигми дозволу в Python.


6

Найпростіший спосіб отримати список методів будь-якого об’єкта - це використовувати help()команду.

%help(object)

У ньому будуть перераховані всі доступні / важливі методи, пов’язані з цим об’єктом.

Наприклад:

help(str)

Що робить %у першому прикладі? Він не працює в моєму Python 2.7.
Скоркіо

@Scorchio Я використовував "%" як підказку замість ">>>" для python. Ви можете зняти% перед запуском команди.
Парітош Вяс


1

Можна створити getAttrsфункцію, яка повертає імена властивостей об'єкта, що викликаються

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

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

Це повернеться

['__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']

1

Не існує надійного способу перерахування всіх методів об'єкта. dir(object)зазвичай корисний, але в деяких випадках він може не перераховувати всі методи. Згідно з dir()документацією : "За допомогою аргументу спробуйте повернути список дійсних атрибутів для цього об'єкта."

Перевірка існування методу може бути здійснена, callable(getattr(object, method))як уже було сказано там.


1

Візьміть список як об’єкт

obj = []

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

Ви отримуєте:

['__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']

0

... чи є принаймні простий спосіб перевірити, чи є у нього певний метод, окрім просто перевірки, чи не виникає помилка при виклику методу

Хоча " простіше просити пробачення, ніж дозволу " - це, безумовно, піфонічний шлях, можливо, що ви шукаєте:

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

0

З метою пошуку певного методу в цілому модулі

for method in dir(module) :
  if "keyword_of_methode" in method :
   print(method, end="\n")

-1

Наприклад, якщо ви використовуєте оболонку плюс, ви можете використовувати це замість цього:

>> MyObject??

таким чином, з '??' одразу після вашого об'єкта він покаже всі атрибути / методи, якими володіє клас.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.