Это - pythonic для функции для возвращения нескольких значений?

80
задан ShadowRanger 11 July 2017 в 19:03
поделиться

9 ответов

Абсолютно (для примера Вы обеспечили).

Кортежи являются гражданами первого класса в Python

существует встроенная функция divmod() , который делает точно это.

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

существуют другие примеры: 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, круглые скобки не необходимы большую часть времени. Цитата от [1 110] Справочное руководство по библиотеке Python:

Кортежи могут быть созданы различными способами:

  • Используя пару круглых скобок для обозначения пустого кортежа: ()
  • Используя запаздывающую запятую для одноэлементного кортежа: a или (a),
  • Разделение объектов с запятыми: a, b, c или (a, b, c)
  • Используя кортеж () встроенный: кортеж () или кортеж (повторяемый)

, Функции должны служить единственной цели

Поэтому, они должны возвратить отдельный объект. В Вашем случае этот объект является кортежем. Рассмотрите кортеж как специальную составную структуру данных. Существуют языки, куда почти каждая функция возвращает несколько значений (список в Lisp).

Иногда достаточно возвратиться (x, y) вместо Point(x, y).

Именованные кортежи

С введением именованных кортежей в Python 2.6 желательно во многих случаях возвращаться названный кортежами вместо простых кортежей.

>>> 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
105
ответ дан ostergaard 24 November 2019 в 09:55
поделиться

Во-первых, обратите внимание, что Python допускает следующее (никакая потребность в круглой скобке):

q, r = divide(22, 7)

Относительно Вашего вопроса, так или иначе нет никакого жесткого правила. Для простого (и обычно изобретаемый) примеры, может казаться, что для заданной функции всегда возможно иметь единственную цель, приводящую к единственному значению. Однако при использовании Python для реальных приложений, Вы быстро сталкиваетесь со многими случаями, где возврат нескольких значений необходим, и приводит к более чистому коду.

Так, я сказал бы, делают то, что имеет смысл, и не пытайтесь соответствовать искусственному соглашению. Python поддерживает несколько возвращаемых значений, так используйте его в надлежащих случаях.

27
ответ дан Joel Spolsky 24 November 2019 в 09:55
поделиться

Примером, который Вы даете, является на самом деле Python встроенная функция, вызванная divmod. Таким образом, кто-то, в какой-то момент вовремя, думал, что это был pythonic достаточно для включения в базовую функциональность.

мне, если это делает инструмент для очистки кода, это - pythonic. Сравните эти два блока кода:

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
13
ответ дан Nathan Jones 24 November 2019 в 09:55
поделиться

Это определенно pythonic. То, что можно возвратить несколько значений из функции шаблон, который Вы имели бы на языке как C, где необходимо определить структуру для каждой комбинации типов, Вы возвращаетесь куда-нибудь.

Однако, если Вы достигаете точки, куда Вы возвращаете что-то сумасшедшее как 10 значений от единственной функции, необходимо серьезно рассмотреть связывание их в классе, потому что в той точке это становится громоздким.

1
ответ дан indentation 24 November 2019 в 09:55
поделиться

Да, возврат нескольких значений (т.е. кортеж) определенно pythonic. Как другие указали, существует много примеров в библиотеке стандарта Python, а также в хорошо уважаемых проектах Python. Два дополнительных комментария:

  1. Возврат нескольких значений иногда очень, очень полезен. Возьмите, например, метод, который дополнительно обрабатывает событие (возвращающий некоторое значение при этом) и также возвращает успешность или неуспешность. Это могло бы возникнуть в цепочке шаблона ответственности. В других случаях Вы хотите возвратить несколько, тесно связанные части данных---как в данном примере. В этой установке возврат нескольких значений сродни возврату единственного экземпляра анонимного класса с несколькими членскими переменными.
  2. обработка Python аргументов метода требует способности непосредственно возвратить несколько значений. В C++, например, аргументы метода могут быть переданы ссылкой, таким образом, можно присвоить выходные значения им, в дополнение к формальному возвращаемому значению. В Python аргументы передаются "ссылкой" (но в смысле Java, не C++). Вы не можете присвоить новые значения аргументам метода и иметь отраженный вне объема метода. Например:

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

    Соответствуют:

    # Python
    def test(arg):
        arg = 1
    
    foo = 0
    test(foo) # foo is still 0
    
3
ответ дан badp 24 November 2019 в 09:55
поделиться

OT: Algol68 RSRE имеет любопытное "/: =" оператор. например,

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

Предоставление частного 3 и остатка от 16.

Примечание: обычно значение" (x/: = y)" отбрасывается, поскольку частное "x" присвоено ссылкой, но в случае RSRE возвращенное значение является остатком.

c.f. Целочисленная Арифметика - Algol68

1
ответ дан NevilleDNZ 24 November 2019 в 09:55
поделиться

Возврат кортежа прохладен. Также отметьте новый namedtuple, который был добавлен в python 2.6, который может сделать это более приемлемым для Вас: http://docs.python.org/dev/library/collections.html#collections.namedtuple

1
ответ дан pixelbeat 24 November 2019 в 09:55
поделиться

Хорошо возвращать несколько значений с помощью кортежа для простых функций такой как divmod. Если это делает код читаемым, это - Pythonic.

, Если возвращаемое значение начинает становиться сбивающим с толку, проверьте, делает ли функция слишком много и разделила его, если это. Если большой кортеж используется как объект, сделайте его объектом. Кроме того, рассмотрите использование именованные кортежи , который будет частью стандартной библиотеки в Python 2.6.

0
ответ дан Will Harris 24 November 2019 в 09:55
поделиться

Я довольно плохо знаком с Python, но метод кортежа кажется очень pythonic мне. Однако у меня была другая идея, которая может улучшить удобочитаемость. Используя словарь предоставляет доступ к различным значениям по имени, а не положению. Например:

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

answer = divide(22, 7)
print answer['quotient']
print answer['remainder']
0
ответ дан Fred Larson 24 November 2019 в 09:55
поделиться
Другие вопросы по тегам:

Похожие вопросы: