Pergunta

Em python, você pode ter uma função retornar vários valores.Aqui está um exemplo imaginário:

def divide(x, y):
    quotient = x/y
    remainder = x % y
    return quotient, remainder  

(q, r) = divide(22, 7)

Isso parece muito útil, mas parece que ele também pode ser abusado ("Bem..função de X já calcula o que precisamos, como um valor intermediário.Vamos ter X devolver esse valor também").

Quando você deve desenhar a linha e definir um método diferente?

Foi útil?

Solução

Absolutamente (para o exemplo fornecido).

Tuplas são cidadãos de primeira classe em Python

Há uma função builtin divmod() que faz exatamente isso.

q, r = divmod(x, y) # ((x - x%y)/y, x%y) Invariant: div*y + mod == x

Há outros exemplos: zip, enumerate, dict.items.

for i, e in enumerate([1, 3, 3]):
    print "index=%d, element=%s" % (i, e)

# reverse keys and values in a dictionary
d = dict((v, k) for k, v in adict.items()) # or 
d = dict(zip(adict.values(), adict.keys()))

BTW, os parênteses não são necessárias na maioria das vezes.Citação do Python Library Reference:

Tuplas podem ser construídos em um número de maneiras:

  • Usando um par de parênteses para indicar o vazio tupla:()
  • Utilizar uma vírgula um singleton tupla:um, ou (a,)
  • Separar os itens com vírgulas:a, b, c ou (a, b, c)
  • Usando a tupla() interno:tuple() ou tupla(iterable)

Funções deve servir como única finalidade

Portanto, eles devem retornar um único objeto.No seu caso, esse objeto é uma tupla.Considere tupla como um ad-hoc composto de estrutura de dados.Há línguas onde quase toda a função retorna vários valores (lista em Lisp).

Às vezes, é suficiente para retornar (x, y) em vez de Point(x, y).

Chamado de tuplas

Com a introdução do chamado tuplas em Python 2.6, é preferível, em muitos casos, para retornar chamado de tuplas em vez de simples tuplas.

>>> import collections
>>> Point = collections.namedtuple('Point', 'x y')
>>> x, y = Point(0, 1)
>>> p = Point(x, y)
>>> x, y, p
(0, 1, Point(x=0, y=1))
>>> p.x, p.y, p[0], p[1]
(0, 1, 0, 1)
>>> for i in p:
...   print(i)
...
0
1

Outras dicas

Em primeiro lugar, observe que em Python permite o seguinte (sem parênteses):

q, r = divide(22, 7)

Quanto à sua pergunta, não há nenhuma regra dura e rápida de qualquer maneira.A simples (e, geralmente artificial) exemplos, pode parecer que é sempre possível para uma determinada função para ter uma única finalidade, resultando em um único valor.No entanto, quando utilizar o Python para aplicações do mundo real, você executar rapidamente em muitos casos, onde a retornar vários valores é necessário, e resulta em código mais limpo.

Então, eu diria que fazer tudo o que faz sentido, e não tenta se ajustar a uma artificial convenção.Python suporta vários valores de retorno, portanto, use-o quando for apropriado.

O exemplo que você dá, na verdade, é um python embutido função, chamada divmod.Então, alguém, em algum momento, pensou que ele era pythonic o suficiente para incluir a funcionalidade do núcleo.

Para mim, se torna o código mais limpo, é pythonic.Compare estes dois blocos de código:

seconds = 1234
minutes, seconds = divmod(seconds, 60)
hours, minutes = divmod(minutes, 60)

seconds = 1234
minutes = seconds / 60
seconds = seconds % 60
hours = minutes / 60
minutes = minutes % 60

Sim, retornar vários valores (por exemplo, uma tupla) é definitivamente pythonic.Como outros já apontaram, há uma abundância de exemplos na biblioteca Python padrão, bem como no bem-respeitado o Python projetos.Dois comentários adicionais:

  1. Retornar vários valores, por vezes, é muito, muito útil.Tome-se, por exemplo, um método que, opcionalmente, manipula um evento (retornar algum valor em fazê-lo) e também retorna sucesso ou fracasso.Esta pode surgir em uma cadeia de responsabilidade de padrão.Em outros casos, você deseja retornar vários, intimamente ligada pedaços de dados---como no exemplo dado.Nesta configuração, a devolver vários valores é semelhante ao retornar de uma única instância de um anônimo classe com várias variáveis de membro.
  2. Python manipulação de argumentos do método exige a capacidade de retornar vários valores.Em C++, por exemplo, o método argumentos podem ser passados por referência, de modo que você pode atribuir valores de saída para eles, além de formal de valor de retorno.Em Python, os argumentos são passados "por referência" (mas no sentido de Java, não C++).Você não pode atribuir novos valores para os argumentos do método e que isso se reflicta fora do escopo do método.Por exemplo:

    // C++
    void test(int& arg)
    {
        arg = 1;
    }
    
    int foo = 0;
    test(foo); // foo is now 1!
    

    Comparar com:

    # Python
    def test(arg):
        arg = 1
    
    foo = 0
    test(foo) # foo is still 0
    

É definitivamente pythonic.O fato de que você pode retornar vários valores de uma função clichê que você teria em uma linguagem como C, onde você precisa definir uma estrutura para cada combinação de tipos de retornar em algum lugar.

No entanto, se você chegar ao ponto onde você está devolvendo algo louco como 10 valores a partir de uma única função, você deve considerar seriamente o empacotamento-los em uma classe, porque nesse ponto, ele se torna muito pesado.

Retornando de uma tupla é legal.Observe também o novo namedtuple qual foi adicionado em python 2.6 o que pode torná-lo mais palatável para você:http://docs.python.org/dev/library/collections.html#collections.namedtuple

OT:RSRE do Algol68 tem a curiosa "/:=" operador.por exemplo.

INT quotient:=355, remainder;
remainder := (quotient /:= 113);

Dando um quociente de 3, e um resto de 16.

Nota:normalmente, o valor de "(x/:=y)" é descartado como quociente de "x" é atribuído por referência, mas em RSRE caso o valor retornado é o resto.

c.f. Inteiro Aritmética - Algol68

É bom retornar vários valores, usando uma tupla para funções simples, tais como divmod.Se torna o código legível, é Pythonic.

Se o valor de retorno começa a tornar-se confuso, verifique se a função está fazendo muito e dividir-se que ele é.Se um grande tupla está sendo usado como um objeto, torná-lo um objeto.Além disso, considere o uso de chamado de tuplas, que fará parte da biblioteca padrão de Python 2.6.

Eu sou bastante novo para Python, mas a tupla técnica parece muito pythonic para mim.No entanto, eu tive outra idéia que pode melhorar a legibilidade.Usando o dicionário permite o acesso a diferentes valores pelo nome, ao invés de posição.Por exemplo:

def divide(x, y):
    return {'quotient': x/y, 'remainder':x%y }

answer = divide(22, 7)
print answer['quotient']
print answer['remainder']
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top