Совершенно верно (для примера, который вы предоставили).
Кортежи - это первоклассные граждане в Python
Есть встроенная функция, divmod()
которая делает именно это.
q, r = divmod(x, y)
Есть и другие примеры: zip
, enumerate
, dict.items
.
for i, e in enumerate([1, 3, 3]):
print "index=%d, element=%s" % (i, e)
d = dict((v, k) for k, v in adict.items())
d = dict(zip(adict.values(), adict.keys()))
Кстати, скобки в большинстве случаев не нужны. Цитата из справочника библиотеки Python :
Кортежи могут быть построены несколькими способами:
- Использование пары круглых скобок для обозначения пустого кортежа: ()
- Использование конечной запятой для одноэлементного кортежа: a или (a,)
- Разделение элементов запятыми: a, b, c или (a, b, c)
- Использование встроенного tuple (): tuple () или tuple (итерация)
Функции должны служить единственной цели
Поэтому они должны возвращать один объект. В вашем случае этот объект является кортежем. Рассматривайте кортеж как специальную составную структуру данных. Есть языки, в которых почти каждая функция возвращает несколько значений (список в Лиспе).
Иногда достаточно вернуться (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
Point(10.5, 11.5)
в 6 раз медленнее, чем{'x': 10.5, 'y':11.5}
. Абсолютные времена635 ns +- 26 ns
против105 ns +- 4 ns
. Маловероятно, что это будет узким местом в приложении - не оптимизируйте, если ваш профилировщик не говорит иначе. Не создавайте классы на уровне функций, если вы не знаете, зачем вам это нужно. Если ваш API требуетdict
чем использоватьdict
- это не имеет никакого отношения к производительности.Во-первых, обратите внимание, что Python допускает следующее (в скобках нет необходимости):
q, r = divide(22, 7)
Что касается вашего вопроса, в любом случае нет жесткого правила. Для простых (и обычно надуманных) примеров может показаться, что данная функция всегда может иметь единственную цель, приводящую к единственному значению. Однако при использовании Python для реальных приложений вы быстро сталкиваетесь со многими случаями, когда необходимо возвращать несколько значений, что приводит к более чистому коду.
Итак, я бы сказал, делайте все, что имеет смысл, и не пытайтесь соответствовать искусственным соглашениям. Python поддерживает несколько возвращаемых значений, поэтому используйте его при необходимости.
источник
q, r
является кортежем.Приведенный вами пример на самом деле является встроенной функцией python с именем
divmod
. Итак, кто-то в какой-то момент подумал, что он достаточно питонический, чтобы включить его в базовую функциональность.Для меня, если это делает код чище, он питонический. Сравните эти два блока кода:
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
источник
Да, возврат нескольких значений (т. Е. Кортежа) определенно питонический. Как отмечали другие, есть много примеров в стандартной библиотеке Python, а также в уважаемых проектах Python. Два дополнительных комментария:
Обработка аргументов метода в 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
источник
Это определенно питонический. Тот факт, что вы можете возвращать несколько значений из функции, которая является шаблоном, который у вас был бы на таком языке, как C, где вам нужно определить структуру для каждой комбинации типов, которые вы где-то возвращаете.
Однако, если вы достигнете точки, когда вы возвращаете что-то сумасшедшее, например 10 значений из одной функции, вам следует серьезно подумать о том, чтобы объединить их в класс, потому что в этот момент это становится громоздким.
источник
Вернуть кортеж - это круто. Также обратите внимание на новый namedtuple, который был добавлен в python 2.6, что может сделать его более приемлемым для вас: http://docs.python.org/dev/library/collections.html#collections. namedtuple
источник
ОТ: В Algol68 RSRE есть любопытный оператор "/: =". например.
INT quotient:=355, remainder; remainder := (quotient /:= 113);
Получаем частное от 3 и остаток от 16.
Примечание: обычно значение «(x /: = y)» отбрасывается, поскольку частное «x» назначается по ссылке, но в случае RSRE возвращаемое значение - это остаток.
cf Целочисленная арифметика - Algol68
источник
Можно вернуть несколько значений, используя кортеж для простых функций, таких как
divmod
. Если это делает код читабельным, то это Pythonic.Если возвращаемое значение начинает сбивать с толку, проверьте, не слишком ли много работает функция, и разделите ее, если это так. Если большой кортеж используется как объект, сделайте его объектом. Также рассмотрите возможность использования именованных кортежей , которые будут частью стандартной библиотеки Python 2.6.
источник
Я новичок в Python, но метод кортежей мне кажется очень питоническим. Однако у меня была другая идея, которая может улучшить читаемость. Использование словаря позволяет получить доступ к различным значениям по имени, а не по положению. Например:
def divide(x, y): return {'quotient': x/y, 'remainder':x%y } answer = divide(22, 7) print answer['quotient'] print answer['remainder']
источник