Eu tenho classes Python, das quais preciso apenas de uma instância em tempo de execução, portanto, seria suficiente ter os atributos apenas uma vez por classe e não por instância. Se houver mais de uma instância (o que não acontecerá), todas as instâncias deverão ter a mesma configuração. Gostaria de saber qual das seguintes opções seria melhor ou mais Python "idiomático".
Variáveis de classe:
class MyController(Controller):
path = "something/"
children = [AController, BController]
def action(self, request):
pass
Variáveis de instância:
class MyController(Controller):
def __init__(self):
self.path = "something/"
self.children = [AController, BController]
def action(self, request):
pass
Respostas:
Se você tiver apenas uma instância de qualquer maneira, é melhor tornar todas as variáveis por instância, simplesmente porque elas serão acessadas (um pouco) mais rapidamente (um nível a menos de "pesquisa" devido à "herança" de classe para instância), e não há desvantagens para pesar contra essa pequena vantagem.
fonte
python -mtimeit
- mas tendo feito isso em python3.4, observo que o acesso a umaint
variável de classe é realmente cerca de 5 a 11 nanossegundos mais rápido que o mesmo que a variável de instância na minha antiga estação de trabalho - não sei ao certo o que codepath faz isso.Mais ecoando os conselhos de Mike e Alex e adicionando minha própria cor ...
Usar atributos de instância é o típico ... o Python mais idiomático. Os atributos de classe não são usados tanto quanto os casos de uso são específicos. O mesmo vale para métodos estáticos e de classe vs. métodos "normais". Eles são construções especiais que abordam casos de uso específicos; caso contrário, é um código criado por um programador aberrante que deseja mostrar que conhece algum canto obscuro da programação em Python.
Alex menciona em sua resposta que o acesso será (um pouco) mais rápido devido a um nível a menos de pesquisa ... deixe-me esclarecer mais para quem ainda não sabe como isso funciona. É muito semelhante ao acesso variável - cuja ordem de pesquisa é:
Para acesso ao atributo, o pedido é:
Ambas as técnicas funcionam de maneira "de dentro para fora", o que significa que os objetos mais locais são verificados primeiro e as camadas externas são verificadas sucessivamente.
No seu exemplo acima, digamos que você esteja procurando o
path
atributo. Quando encontrar uma referência como "self.path
", o Python examinará os atributos da instância primeiro para uma correspondência. Quando isso falha, verifica a classe da qual o objeto foi instanciado. Por fim, ele pesquisará as classes base. Como Alex afirmou, se o seu atributo for encontrado na instância, ele não precisará procurar em outro lugar, portanto, você economizará um pouco de tempo.No entanto, se você insistir nos atributos da classe, precisará dessa pesquisa extra. Ou , sua outra alternativa é se referir ao objeto por meio da classe em vez da instância, por exemplo, em
MyController.path
vez deself.path
. Essa é uma pesquisa direta que contorna a pesquisa adiada, mas, como alex menciona abaixo, é uma variável global; portanto, você perde aquele pedaço que pensou em salvar (a menos que crie uma referência local ao nome da classe [global] )A conclusão é que você deve usar atributos de instância na maioria das vezes. No entanto, haverá ocasiões em que um atributo de classe é a ferramenta certa para o trabalho. O código que usa os dois ao mesmo tempo exigirá a maior diligência, pois o uso
self
apenas fornecerá o objeto de atributo da instância e sombreia o acesso ao atributo de classe com o mesmo nome. Nesse caso, você deve usar acessar o atributo pelo nome da classe para fazer referência a ele.fonte
MyController
é procurado nas globais, então o custo total é maior do que o localself.path
ondepath
está uma variável de instância (já queself
é local para o método == pesquisa super-rápida).Em caso de dúvida, você provavelmente deseja um atributo de instância.
Os atributos de classe são mais reservados para casos especiais em que fazem sentido. O único caso de uso muito comum são os métodos. Não é incomum usar atributos de classe para constantes somente leitura que as instâncias precisam saber (embora o único benefício disso seja se você também deseja acessar de fora da classe), mas certamente deve ser cauteloso ao armazenar qualquer estado nelas , o que raramente é o que você deseja. Mesmo que você tenha apenas uma instância, escreva a classe como faria com qualquer outra, o que geralmente significa usar atributos de instância.
fonte
avoid global variables
e sua definição é que variáveis globais também são variáveis declaradas como atributos de classe. No entanto, o próprio guia de estilo do Python ( PEP-8 ) deve ser o primeiro lugar para perguntas desse tipo. Então, sua mente deve ser a ferramenta de escolha (é claro que você também pode obter idéias do Google, por exemplo).Mesma pergunta em Desempenho de acessar variáveis de classe em Python - o código aqui adaptado de @Edward Loper
As variáveis locais são as mais rápidas de acessar, praticamente ligadas às variáveis de módulo, seguidas pelas variáveis de classe e pelas variáveis de instância.
Existem 4 escopos nos quais você pode acessar variáveis:
O teste:
O resultado:
fonte