Me deparei com algo assim em um projeto de código aberto. Os métodos que modificam os atributos da instância retornam uma referência para a instância. Qual é o objetivo dessa construção?
class Foo(object):
def __init__(self):
self.myattr = 0
def bar(self):
self.myattr += 1
return self
python
method-chaining
nate c
fonte
fonte
Respostas:
É para permitir o encadeamento.
Por exemplo:
Agora você pode dizer:
fonte
Como mencionam @Lie Ryan e @Frank Shearar, isso é chamado de "interface fluente", mas esse padrão existe há muito tempo.
A parte controversa desse padrão é que, em OO, você tem um estado mutável; portanto, um método nulo possui um tipo de valor de retorno implícito de
this
- ou seja, o objeto com estado atualizado é o tipo de valor de retorno.Portanto, em uma linguagem OO com estado mutável, esses dois são mais ou menos equivalentes:
... em oposição a
Então, ouvi pessoas no passado resistirem a interfaces fluentes porque gostam da primeira forma. Outro nome que ouvi por "interface fluente" é "acidente de trem";)
Eu digo "mais ou menos equivalente", no entanto, porque as interfaces fluentes adicionam uma ruga. Eles não precisam "devolver isso". Eles podem "retornar novos". Essa é uma maneira de obter objetos imutáveis no OO.
Então você pode ter uma classe A que faz (pseudocódigo)
Agora, cada método retorna um novo objeto, mantendo o objeto inicial inalterado. E essa é uma maneira de entrar em objetos imutáveis sem alterar muito o seu código.
fonte
new(...)
, isso vazará memória.__init__
repetidamente também gera sobrecarga.A maioria das linguagens conhece o idioma 'auto-retorno' e o ignora se não for usado em uma linha. No entanto, é notável que, em Python, as funções retornem
None
por padrão.Quando eu estava na escola de informática, meu instrutor fez um grande acordo sobre a diferença entre funções, procedimentos, rotinas e métodos; muitas perguntas sobre ensaios de aperto de mãos foram feitas com lapiseiras esquentando minhas mãos sobre tudo isso.
Basta dizer que retornar self é a maneira OO definitiva de criar métodos de classe, mas o Python permite vários valores de retorno, tuplas, listas, objetos, primitivos ou Nenhum.
O encadeamento, como eles dizem, é apenas colocar a resposta da última operação na próxima, e o tempo de execução do Python pode otimizar esse tipo de coisa. A compreensão da lista é uma forma interna disso. (Muito poderoso!)
Portanto, no Python, não é tão importante que todo método ou função retorne coisas, e é por isso que o padrão é Nenhum.
Existe uma escola de pensamento de que toda ação em um programa deve relatar seu sucesso, falha ou resultado de volta ao seu contexto ou objeto de chamada, mas não estava falando aqui dos Requisitos do DOD ADA aqui. Se você precisar obter feedback de um método, vá em frente ou não, mas tente ser consistente.
Se um método pode falhar, ele deve retornar com êxito ou falha ou gerar uma exceção a ser tratada.
Uma ressalva é que, se você usar o idioma próprio de retorno, o Python permitirá que você atribua todos os seus métodos a variáveis e você pode pensar que está obtendo um resultado ou uma lista de dados quando realmente está obtendo o objeto.
Linguagens de tipo restritivo gritam e gritam e quebram quando você tenta fazer isso, mas as interpretadas (Python, Lua, Lisp) são muito mais dinâmicas.
fonte
No Smalltalk, todo método que não retorna algo explicitamente tem um "eu de retorno" implícito.
Isso ocorre porque (a) fazer com que todo método retorne algo torna o modelo de computação mais uniforme e (b) é muito útil que os métodos retornem a si próprios. Josh K dá um bom exemplo.
fonte
Python
, todo método que não retorna algo explicitamente, tem um "retorno Nenhum" implícito.Prós de retornar um objeto (
return self
)Exemplo:
Estilo mais popular na comunidade de programação (eu acho).
Prós de mudar um objeto (não
return self
)return
para outros fins.fonte