Проверка существования функции python

Как проверить, существует ли метод в Python?

В функции __getattr__() , если указанная переменная не найдена, она дает ошибку. Как проверить, существует ли переменная или метод как часть объекта?

import string import logging class Dynamo: def __init__(self,x): print "In Init def" self.x=x def __repr__(self): print self.x def __str__(self): print self.x def __int__(self): print "In Init def" def __getattr__(self, key): print "In getattr" if key == 'color': return 'PapayaWhip' else: raise AttributeError dyn = Dynamo('1') print dyn.color dyn.color = 'LemonChiffon' print dyn.color dyn.__int__() dyn.mymethod() //How to check whether this exist or not 

8 ответов

Проще просить прощения, чем спрашивать разрешения.

Не проверяйте, существует ли метод. Не тратьте ни одной строки кода на «проверку»

try: dyn.mymethod() # How to check whether this exists or not # Method exists and was used. except AttributeError: # Method does not exist; What now? 

Но, возможно, он действительно не хочет вызывать его, просто чтобы проверить, существует ли этот метод (как в моем случае) .

В отличие от .NET, это на самом деле более производительно, чем проверка, существует ли метод. Я удивлен (в хорошем смысле).

как говорит @DK, это приведет к перехвату любой ошибки AttributeError, которая может быть вызвана проверяемым методом, что может быть нежелательно (не говоря уже о том, что в этом случае это приведет к неверному выводу об отсутствии метода).

@ashes999 ashes999 Не могли бы вы указать какой-нибудь официальный или хорошо документированный источник, подтверждающий это, пожалуйста?

@Rick77 Rick77 возможно мой комментарий плохо написан. В .NET исключения довольно тяжелые и медленные; Разработчик .NET проверит, существует ли метод, чтобы избежать исключения. В Python исключения довольно легкие и быстрые. У меня нет документов, чтобы доказать это, извините.

Читайте также:  Python определить тип элемента

Я хочу понять, является ли использование исключений вместо проверки правильным подходом в python (такого нет в большинстве языков, поэтому исключения так называются . ). В своем комментарии вы написали, что [вызов функции и перехват исключений, я полагаю] на самом деле более производительный, чем проверка существования метода , и мне хотелось бы знать, откуда у вас эта информация, вот и все .

@ashes999 ashes999 помимо факта облегченных исключений, это плохой признак — проверка существования метода не должна быть дольше, чем простая проверка переменной в памяти, в то время как исключения включали бы эту проверку , и над этим выполнялась некоторая другая работа ( нравится собирать описание) . Я предполагаю, что это была какая-то ошибка, и вы не должны полагаться на такую скорость.

В принципе это хорошо, и в Python, в отличие от других языков, есть культура «исключения как поток управления». Однако, если вы используете инструменты регистрации исключений, такие как Sentry / Raven или New Relic, такие исключения необходимо отфильтровывать по отдельности (если это возможно) или создавать шум. Я бы предпочел проверить, существует ли метод, а не вызывать его.

ОП спросил «Как проверить, существует ли метод в Python?» не «Как выполнить метод, который может не существовать?». Вы ответили на другой вопрос.

Это не правильно на многих уровнях. Сам метод может вызвать AttributeError, и это будет обнаружено, поскольку метод не существует! Это также разрушает поддержку отладчика для взлома исключений. Я также уверен, что это, вероятно, влияет на производительность, если все было в порядке. Последний, но не список. Я не хочу выполнять метод, просто проверьте, существует ли он. Вы должны рассмотреть возможность удаления этого ответа или, по крайней мере, поместить все эти предупреждения, чтобы наивные люди не вводили в заблуждение.

Читайте также:  Azsgazprom ru index php

Проверьте, имеет ли класс такой метод?

hasattr(Dynamo, key) and callable(getattr(Dynamo, key)) 
hasattr(Dynamo, 'mymethod') and callable(getattr(Dynamo, 'mymethod')) 

Вы можете использовать self.__class__ вместо Dynamo

None них не может быть callable(getattr(Dynamo, ‘mymethod’, None)) , поэтому вы можете просто callable(getattr(Dynamo, ‘mymethod’, None)) . Я использовал этот ответ, потому что мой super (). Mymethod () мог бросить AttributeError

@sbutler Интересно, что это работает. Согласно PyCharm, подпись для getattr является def getattr(object, name, default=None): я подозреваю, что это не точно, потому что если бы это было так, я бы ожидал, что передача None в качестве третьего параметра не изменит поведение функции.

@bszom: В оболочке python help(getattr) говорит: «Когда задан аргумент по умолчанию, он возвращается, когда атрибут не существует; без него в этом случае возникает исключение». — (и действительно, вы можете проверить, что getattr действительно вызывает исключение, если атрибут отсутствует) настолько ясно, что бы PyCharm ни был, это неправильно.

@bszom Я обнаружил, что здесь обсуждается такое поведение getattr : stackoverflow.com/q/32499863/1545579

Вы можете попробовать использовать модуль ‘inspect’:

import inspect def is_method(obj, name): return hasattr(obj, name) and inspect.ismethod(getattr(obj, name)) is_method(dyn, 'mymethod') 

Может быть, так, если все методы вызываются

app = App(root) # some object call app att = dir(app) #get attr of the object att #['doc', 'init', 'module', 'button', 'hi_there', 'say_hi'] for i in att: if callable(getattr(app, i)): print 'callable:', i else: print 'not callable:', i 

Как насчет поиска в dyn.__dict__ ?

try: method = dyn.__dict__['mymethod'] except KeyError: print "mymethod not in dyn" 

Префикс с двойным подчеркиванием плюс суффикс с двойным подчеркиванием означает «это обычно используется самим интерпретатором Python», и обычно есть какой-то способ добиться того же эффекта от пользовательской программы для наиболее распространенных случаев использования (в этом случае это будет используя точечную нотацию для атрибута), но это не запрещено и не неправильно использовать его, если ваш вариант использования действительно требует этого.

Читайте также:  Maven java что такое

Это не запрещено. Ошибочность субъективна: она зависит от того, насколько сильно вы хотите запутать программистов, придерживающихся соглашений: не используйте их, если у вас нет альтернативы.

Если ваш метод находится за пределами класса, и вы не хотите его запускать и создавать исключение, если оно не существует:

Я думаю, вам стоит посмотреть на пакет inspect . Это позволяет вам «обернуть» некоторые из вещей. Когда вы используете метод dir , он также отображает встроенные методы, унаследованные методы и все другие атрибуты, делающие возможными конфликты, например:

class One(object): def f_one(self): return 'class one' class Two(One): def f_two(self): return 'class two' if __name__ == '__main__': print dir(Two) 

Массив, который вы получаете из dir(Two) , содержит как f_one , так и f_two и множество встроенных файлов. С помощью inspect вы можете сделать это:

class One(object): def f_one(self): return 'class one' class Two(One): def f_two(self): return 'class two' if __name__ == '__main__': import inspect def testForFunc(func_name): ## Only list attributes that are methods for name, _ in inspect.getmembers(Two, inspect.ismethod): if name == func_name: return True return False print testForFunc('f_two') 

В этих примерах все еще перечислены оба метода в двух классах, но если вы хотите ограничить проверку только функцией в определенном классе, для этого требуется немного больше работы, но это абсолютно возможно.

Источник

Оцените статью