Por que você precisa de si mesmo? em Python para se referir a variáveis ​​de instância?

13

Tenho programado em várias linguagens como Java, Ruby, Haskell e Python. Eu tenho que alternar entre vários idiomas por dia devido a diferentes projetos nos quais trabalho. Agora, o problema é que muitas vezes esqueço de escrever selfcomo o primeiro parâmetro nas definições de função no Python. O mesmo ocorre com a chamada de métodos no mesmo objeto.

Dito isto, estou bastante impressionado com essa abordagem do Python. Basicamente, precisamos digitar mais para realizar as tarefas, nas linguagens como Java e Ruby, as coisas são simplificadas pela referência automática às variáveis ​​no objeto atual.

Minha pergunta é por que isso é selfnecessário? É uma escolha puramente de estilo ou existe uma razão pela qual o Python não pode deixar você omitir selfa maneira como Java e C ++ o deixam this?

vivek
fonte
1
@gnat agora apenas profissionais, e seriamente uma boa pergunta que está me incomodando desde alguns dias, por favor, não a mate votando.
vivek
2
Esta questão foi abordada mais do que completamente em stackoverflow.com/questions/2709821/… .
David Arno
Meu entendimento é que ele se baseia no estilo C de passar um ponteiro para uma estrutura como o primeiro argumento.
21415 Dannnno
Escrever @staticmethodantes da declaração do método, suprime o erro (apenas para informações e também não é recomendado)
Yash

Respostas:

23

1) Por que é selfexigido como parâmetro explícito nas assinaturas de métodos?

Porque métodos são funções e foo.bar(baz)são apenas açúcar sintático para bar(foo, baz). Classes são apenas dicionários em que alguns dos valores são funções. (Construtores também são apenas funções, e é por isso que o Python não precisa new). Você pode dizer que o Python torna explícito que os objetos são criados a partir de componentes mais simples. Isso está de acordo com a filosofia "explícito é melhor que implícito".

Por outro lado, em Java, os objetos são realmente mágicos e não podem ser reduzidos a componentes mais simples da linguagem. Em Java (pelo menos até Java 8), uma função é sempre um método de propriedade de um objeto, e essa propriedade não pode ser alterada devido à natureza estática da linguagem. Portanto, não há ambiguidade sobre o que thisse refere, portanto, faz sentido tê-lo definido implicitamente.

JavaScript é um exemplo de uma linguagem implícita thiscomo Java, mas onde funções podem existir separadamente de objetos como em Python. Isso leva a muita confusão sobre o que thisse refere a quando funções são passadas e chamadas em diferentes contextos. Muitos pensam instintivamente que thisdevem se referir a alguma propriedade intrínseca da função, enquanto na verdade é puramente determinada pela maneira como a função é chamada. Eu acredito que ter thiscomo parâmetro explícito como em Python tornaria isso muito menos confuso.

Alguns outros benefícios do selfparâmetro explícito :

  • Decoradores são apenas funções que envolvem outras funções. Como os métodos são apenas funções, os decoradores funcionam tão bem quanto os métodos. Se houvesse algum tipo de identidade implícita, os decoradores não trabalhariam de maneira transparente nos métodos.

  • Métodos de classe e métodos estáticos não aceitam um parâmetro de instância. Os métodos de classe usam uma classe como o primeiro argumento (normalmente chamado cls). O parâmetro explícito selfou clstorna muito mais claro o que está acontecendo e o que você tem acesso no método.

2) Por que as variáveis ​​de instância sempre devem ser qualificadas com " self.?

Em Java, você não precisa prefixar variáveis ​​de membro com " this.", mas em Python " self." é sempre necessário. O motivo é que o Python não possui uma sintaxe explícita para declarar variáveis; portanto, não há como saber se x = 7deve declarar uma nova variável local ou atribuir a uma variável membro. A especificação self.resolve essa ambiguidade.

JacquesB
fonte
A referência implícita à variável de membro (sem self., como Java) é fundamentalmente incompatível com as regras de escopo e, quando você precisa ser explícito lá, estar implícito no parâmetro não faz mais tanto sentido.
Jan Hudec
@ JanHudec: Bom, ponto. Eu adicionei à resposta.
JacquesB
6

Há uma razão bastante simples pela qual o AFAIK não foi realmente abordado na duplicata entre sites, nem aqui: o Python começou como uma linguagem processual. Foi baseado no ABC, também uma linguagem processual.

A Orientação a Objetos foi adicionada mais tarde e, quando foi adicionado, Guido van Rossum queria adicionar a quantidade mínima de recursos possível, a fim de manter o design do Python simples. O Python já tinha dicts e funções, então, por que adicionar algo inteiramente novo à linguagem, quando um objeto pode simplesmente ser um dictdos slots e uma classe pode simplesmente ser uma dictdas funções? Um método pode ser interpretado como uma função parcialmente aplicada que fecha sobre um único argumento distinto. E é exatamente assim que os métodos são implementados no Python: eles não são. São apenas funções que recebem um argumento distinto extra.

Jörg W Mittag
fonte
Acredito que o Python suportava o OO e tinha classes e herança desde a primeira versão lançada. Pelo menos é o que a wikipedia me diz. Mas o processo de van Rossums no design inicial do idioma pode ter sido o que você descreve.
precisa saber é o seguinte
Obrigado pelo link, é uma leitura realmente interessante.
JacquesB
2

Aqui estão minhas conclusões com base nas respostas acima e na leitura das divagações do Guido sobre este tópico:

A grande ideia

As funções são os blocos de construção importantes no Python (ou deveríamos dizer o único); na verdade, estamos meio que emulando o OOP usando funções.

Dado que uma classe nada mais é que um dicionário de funções, podemos anexar qualquer função a qualquer classe em tempo de execução. Basicamente, devido a essa necessidade de lançar as funções em tempo de execução, podemos fazer coisas como Monkey Patching . Aqui, o selfparâmetro que suporta o polimorfismo paramétrico.

vivek
fonte
1
Perguntas auto-respondidas são encorajadas quando sua resposta é de alta qualidade. Quando comparo sua resposta aqui com as outras, fico me perguntando por que você sentiu que precisava adicionar isso. As outras respostas são mais aprofundadas e acrescentam mais detalhes do que a sua resposta.
1
@ GlenH7, a resposta foi apenas para minha referência, porque toda vez que eu não consigo ler a resposta de todos de novo e de novo. Em relação à qualidade, diga-me se alguma informação é enganosa. De qualquer forma, geralmente espero de 2 a 3 dias para aceitar qualquer resposta.
vivek
A votação em baixa está se tornando moeda barata e todo mundo aqui está gastando com as duas mãos sem saber seu significado. Você percebe que se alguém vier aqui, veja esta resposta votada em baixo, assumiria que está errada!
vivek