Estou escrevendo um algoritmo de pesquisa de espaço de estado da IA e tenho uma classe genérica que pode ser usada para implementar rapidamente um algoritmo de pesquisa. Uma subclasse definiria as operações necessárias e o algoritmo fará o resto.
Aqui é onde eu fico preso: Eu quero evitar a regeneração do estado pai repetidamente, para que eu tenha a seguinte função, que retorna as operações que podem ser aplicadas legalmente em qualquer estado:
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
E a função invert_op lança por padrão.
Existe uma maneira mais rápida de verificar se a função não está definida do que capturar uma exceção?
Eu estava pensando em algo nas linhas de verificação do presente no dir, mas isso não parece certo. O hasattr é implementado chamando getattr e verificando se aumenta, o que não é o que eu quero.
has_op = lambda obj, op: callable(getattr(obj, op, None))
hasattr(connection, 'invert_opt')
.Respostas:
Sim, use
getattr()
para obter o atributo ecallable()
verificar se é um método:Observe que
getattr()
normalmente lança uma exceção quando o atributo não existe. No entanto, se você especificar um valor padrão (None
nesse caso), ele retornará isso.fonte
getattr
neste caso captura uma exceção silenciosamente e retorna o valor padrão, comohasattr
faz, contra o qual o OP foi por algum motivo.Funciona em Python 2 e Python 3
hasattr
retornaTrue
se o objeto de conexão tiver uma funçãoinvert_opt
definida. Aqui está a documentação para você pastarhttps://docs.python.org/2/library/functions.html#hasattr https://docs.python.org/3/library/functions.html#hasattr
fonte
connection.invert_opt = 'foo'
.Por que você é contra isso? Na maioria dos casos pitônicos, é melhor pedir perdão do que permissão. ;-)
Novamente, por que isso? O seguinte é bastante pitônico:
Ou,
Observe, no entanto, que isso
getattr(obj, attr, default)
é basicamente implementado capturando uma exceção também. Não há nada de errado nisso na terra dos Python!fonte
As respostas aqui verificam se uma sequência é o nome de um atributo do objeto. Uma etapa extra (usando callable) é necessária para verificar se o atributo é um método.
Portanto, tudo se resume a: qual é a maneira mais rápida de verificar se um objeto obj possui um atributo attribute. A resposta é
Isso ocorre porque um ditado faz o hash de suas chaves, portanto, verificar a existência da chave é rápido.
Veja comparações de tempo abaixo.
fonte
__slots__
.__slots__
ajude a acelerar o acesso a atributos em ~ 10%. stackoverflow.com/a/14119024/1459669Gosto da resposta de Nathan Ostgard e votei positivamente. Mas outra maneira de resolver seu problema seria usar um decorador de memorização, que armazenaria em cache o resultado da chamada de função. Portanto, você pode seguir em frente e ter uma função cara que descobre algo, mas quando você liga várias vezes, as chamadas subsequentes são rápidas; a versão memorizada da função procura os argumentos em um ditado, encontra o resultado no ditado a partir do momento em que a função real calculou o resultado e retorna o resultado imediatamente.
Aqui está uma receita para um decorador de memorização chamado "lru_cache", de Raymond Hettinger. Uma versão disso agora é padrão no módulo functools no Python 3.2.
http://code.activestate.com/recipes/498245-lru-and-lfu-cache-decorators/
http://docs.python.org/release/3.2/library/functools.html
fonte
Como qualquer coisa em Python, se você se esforçar o suficiente, pode se esforçar e fazer algo realmente desagradável. Agora, aqui está a parte desagradável:
Por favor, faça-nos um favor, continue fazendo o que você tem na sua pergunta e NÃO use isso a menos que esteja na equipe do PyPy invadindo o interpretador do Python. O que você tem lá em cima é pitônico, o que eu tenho aqui é puro MAL .
fonte
co_names
é igual a('NotImplementedError',)
. Não tenho certeza se isso o torna mais ou menos mau, no entanto.Você também pode passar por cima da turma:
fonte
Embora a verificação de atributos na propriedade __dict__ seja realmente rápida, você não pode usá-lo para métodos, pois eles não aparecem no hash __dict__. Você pode, no entanto, recorrer a soluções alternativas hackeadas em sua classe, se o desempenho for crítico:
Em seguida, verifique o método como:
Comparação de tempo com
getattr
:Não que eu esteja encorajando essa abordagem, mas parece funcionar.
[EDIT] O aumento de desempenho é ainda maior quando o nome do método não está em uma determinada classe:
fonte
__dict__
pode ser substituído. Não pode ser confiável.