Я пишу алгоритм поиска в пространстве состояний AI, и у меня есть общий класс, который можно использовать для быстрой реализации алгоритма поиска. Подкласс будет определять необходимые операции, а алгоритм сделает все остальное.
Вот где я застрял: я хочу избежать повторного создания родительского состояния снова и снова, поэтому у меня есть следующая функция, которая возвращает операции, которые могут быть законно применены к любому состоянию:
def get_operations(self, include_parent=True):
ops = self._get_operations()
if not include_parent and self.path.parent_op:
try:
parent_inverse = self.invert_op(self.path.parent_op)
ops.remove(parent_inverse)
except NotImplementedError:
pass
return ops
А функция invert_op по умолчанию выдает.
Есть ли более быстрый способ проверить, не определена ли функция, чем перехват исключения?
Я думал что-то вроде проверки наличия в каталоге, но это не кажется правильным. hasattr реализуется путем вызова getattr и проверки его повышения, чего я не хочу.
has_op = lambda obj, op: callable(getattr(obj, op, None))
hasattr(connection, 'invert_opt')
.Ответы:
Да, используйте
getattr()
для получения атрибута иcallable()
проверки того, что это метод:Обратите внимание, что
getattr()
обычно выдает исключение, когда атрибут не существует. Однако, если вы укажете значение по умолчанию (None
в данном случае), оно вернет его.источник
getattr
в этом случае автоматически перехватывает исключение и вместо этого возвращает значение по умолчанию, как иhasattr
делает, против чего OP был по какой-то причине.Он работает как в Python 2, так и в Python 3.
hasattr
возвращается,True
если для объекта подключения определена функцияinvert_opt
. Вот документация для вас, чтобы пастисьhttps://docs.python.org/2/library/functions.html#hasattr https://docs.python.org/3/library/functions.html#hasattr
источник
connection.invert_opt = 'foo'
.Почему ты против этого? В большинстве случаев с Pythonic лучше попросить прощения, чем разрешения. ;-)
Опять же, почему? Следующее довольно Pythonic:
Или,
Обратите внимание, однако, что
getattr(obj, attr, default)
это в основном также реализуется путем перехвата исключения. В стране Python нет ничего плохого!источник
Ответы здесь проверяют, является ли строка именем атрибута объекта. Дополнительный шаг (с использованием callable) необходим, чтобы проверить, является ли атрибут методом.
Итак, все сводится к следующему: каков самый быстрый способ проверить, имеет ли объект obj атрибут attrib. Ответ
Это так, потому что dict хеширует свои ключи, поэтому проверка наличия ключа выполняется быстро.
См. Сравнение времени ниже.
источник
__slots__
.__slots__
помочь ускорить доступ к атрибутам на ~ 10%. stackoverflow.com/a/14119024/1459669Мне нравится ответ Натана Остгарда, и я проголосовал за него. Но другой способ решить вашу проблему - использовать мемоизирующий декоратор, который кэширует результат вызова функции. Таким образом, вы можете использовать дорогостоящую функцию, которая что-то вычисляет, но затем, когда вы вызываете ее снова и снова, последующие вызовы выполняются быстро; мемоизированная версия функции ищет аргументы в dict, находит результат в dict, когда фактическая функция вычисляла результат, и сразу же возвращает результат.
Вот рецепт мемоизирующего декоратора под названием "lru_cache" от Раймонда Хеттингера. Версия этого теперь является стандартной в модуле functools в Python 3.2.
http://code.activestate.com/recipes/498245-lru-and-lfu-cache-decorators/
http://docs.python.org/release/3.2/library/functools.html
источник
Как и все в Python, если вы будете достаточно стараться, вы можете выйти из-под контроля и сделать что-нибудь действительно неприятное. А теперь самое неприятное:
Пожалуйста , нам одолжение, просто продолжать делать то , что у вас есть в вашем вопросе и НЕ когда - либо использовать это , если вы не в команде PyPy взлома в интерпретатор Python. У вас там Pythonic, а у меня - чистое ЗЛО .
источник
co_names
равно ли('NotImplementedError',)
. Однако я не уверен, делает ли это более или менее злым.Вы также можете пройтись по классу:
источник
Хотя проверка атрибутов в свойстве __dict__ выполняется очень быстро, вы не можете использовать это для методов, поскольку они не отображаются в хэше __dict__. Однако вы можете прибегнуть к хакерскому обходному пути в своем классе, если производительность настолько критична:
Затем проверьте метод как:
Сравнение времени с
getattr
:Не то чтобы я поощрял этот подход, но, похоже, он работает.
[EDIT] Повышение производительности еще выше, если имя метода не принадлежит данному классу:
источник
__dict__
может быть отменено. Этому нельзя доверять.