Diferença entre a definição de um membro __init__ para definir a ele no corpo da classe em python?

StackOverflow https://stackoverflow.com/questions/1549722

  •  20-09-2019
  •  | 
  •  

Pergunta

Qual é a diferença entre fazer

class a:
   def __init__(self):
       self.val=1

para fazer

class a:
   val=1
   def __init__(self):
       pass
Foi útil?

Solução

class a:
   def __init__(self):
       self.val=1

isso cria uma classe (no Py2, um cruddy, legado, de estilo antigo, não faça isso! de classe;em Py3, o velho desagradável legado classes de ter finalmente ido embora, então esta seria uma classe de um e apenas um tipo -- o **bom* tipo, o que requer class a(object): em Py2), de modo que cada instância começa com sua própria referência para o objeto inteiro 1.

class a:
   val=1
   def __init__(self):
       pass

isso cria uma classe (da mesma espécie), que tem em si uma referência para o objeto inteiro 1 (seu instâncias começar com nenhum por instância de referência).

Para immutables como int valores, é difícil ver uma diferença prática.Por exemplo, em ambos os casos, se, mais tarde, fazer self.val = 2 em uma instância de a, isso vai fazer uma instância referência (já existente resposta é muito errado a este respeito).

A distinção é importante para mutable objetos, porque têm mutator métodos, por isso é muito crucial para saber se uma determinada lista é sem igual, por instância ou compartilhado entre todas as instâncias.Mas para imutável objetos, desde que você nunca pode mudar o objeto em si, mas apenas atribuir (por exemplo,para self.val, que se fará sempre por instância de referência), é muito menor.

A única diferença relevante para immutables:se, posteriormente, atribuir a.val = 3, no primeiro caso , isso afetará o que é visto como self.val por cada instância (exceto para os casos que tinham o seu próprio self.val atribuído ou equivalente ações);no segundo caso, ele não afetará o que é visto como self.val por qualquer instância (exceto para os casos de que você tinha realizado del self.val ou equivalente ações).

Outras dicas

Outros têm explicou as diferenças técnicas.Eu vou tentar explicar por que você pode querer usar variáveis de classe.

Se você está apenas instanciar a classe de uma vez e, em seguida, variáveis de classe de forma eficaz são variáveis de instância.No entanto, se você está fazendo muitas cópias, ou deseja compartilhar o estado entre algumas instâncias, em seguida, variáveis de classe são muito úteis.Por exemplo:

class Foo(object):
    def __init__(self):
        self.bar = expensivefunction()

myobjs = [Foo() for _ in range(1000000)]

vai causar expensivefunction() ser chamado de um milhão de vezes.Se ele vai retornar o mesmo valor de cada vez, dizem buscar um parâmetro de configuração a partir de um banco de dados, então você deve considerar a movê-lo para a definição de classe de modo que é chamado somente uma vez e depois compartilhado em todas as instâncias.

Eu também utilizar variáveis de classe muito quando memoizing resultados.Exemplo:

class Foo(object):
    bazcache = {}

    @classmethod
    def baz(cls, key):
        try:
            result = cls.bazcache[key]
        except KeyError:
            result = expensivefunction(key)
            cls.bazcache[key] = result
        return result

Neste caso, baz é um método de classe;seu resultado não depende de quaisquer variáveis de instância.Isso significa que podemos manter uma cópia dos resultados de cache na classe de variável, de modo que: 1) não armazenar os mesmos resultados várias vezes, e 2) cada instância pode se beneficiar de resultados que foram armazenados em cache a partir de outras instâncias.

Para ilustrar, suponha que você tem um milhão de casos, cada operacional, sobre os resultados de uma pesquisa Google.Você provavelmente prefiro muito mais que todos esses objetos compartilham os resultados de cada um executar a pesquisa e aguarde a resposta.

Portanto, gostaria de discordar com Lennart aqui.Variáveis de classe são muito conveniente, em determinados casos.Quando eles são a ferramenta certa para o trabalho, não hesite em usá-los.

Como mencionado por outros, em um caso, é um atributo na classe, por outro, um atributo na instância. Isso importa? Sim, em um caso, sim. Como Alex disse, se o valor for mutável. A melhor explicação é o código, então adicionarei algum código para mostrá -lo (essa é tudo essa resposta, na verdade):

Primeiro, uma classe definindo dois atributos de instância.

>>> class A(object):
...     def __init__(self):
...         self.number = 45
...         self.letters = ['a', 'b', 'c']
... 

E então uma classe definindo dois atributos de classe.

>>> class B(object):
...     number = 45
...     letters = ['a', 'b', 'c']
... 

Agora nós os usamos:

>>> a1 = A()
>>> a2 = A()
>>> a2.number = 15
>>> a2.letters.append('z')

E tudo está bem:

>>> a1.number
45
>>> a1.letters
['a', 'b', 'c']

Agora use a variação do atributo de classe:

>>> b1 = B()
>>> b2 = B()
>>> b2.number = 15
>>> b2.letters.append('z')

E tudo é ... bem ...

>>> b1.number
45
>>> b1.letters
['a', 'b', 'c', 'z']

Sim, observe que, quando você mudou, o atributo de classe mutável mudou para todas as classes. Normalmente, isso não é o que você quer.

Se você estiver usando o ZODB, usa muitos atributos de classe porque é uma maneira útil de atualizar objetos existentes com novos atributos ou adicionar informações em um nível de classe que não se persiste. Caso contrário, você pode ignorá -los praticamente.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top