Чаму ж няма картэж разумення ў Python?

Як мы ўсе ведаем, што ёсць спіс разуменне, як

[i for i in [1, 2, 3, 4]]

і ёсць слоўнік разуменне, як

{i:j for i, j in {1: 'a', 2: 'b'}.items()}

але

(i for i in (1, 2, 3))

у канчатковым выніку ў генератары, а не картэж разуменне. Чаму гэта?

My guess is that a tuple is immutable, але this does not seem to be the answer.

190
Там таксама набор разуменне - які выглядае вельмі падобна на Dict разумення ...
дададзена аўтар mgilson, крыніца
Існуе памылка сінтаксісу ў кодзе: {я: J для I, J ў {1: 'а', 2: 'б'}} павінен быць {я: J для г , J ў {1: 'а', 2: 'Ь'}. пунктаў ()}
дададзена аўтар Inbar Rose, крыніца
Проста дзеля нашчадкаў, ёсць дыскусія з гэтай нагоды адбываецца ў Python чат
дададзена аўтар Inbar Rose, крыніца
Па-відаць, ёсць. stackoverflow.com/a/51811147/9627166
дададзена аўтар Super S, крыніца
@InbarRose Дзякуй за паказаўшы яго -.-
дададзена аўтар Shady Xu, крыніца

10 адказы

Вы можаце выкарыстоўваць выраз генератара:

tuple(i for i in (1, 2, 3))

але круглыя ​​дужкі былі ўжо прынятыя для .. генератарных выразаў.

285
дададзена
Да гэтага аргументу, мы маглі б сказаць, спіс зразуменне непатрэбна таксама: Спіс (I для г у (1,2,3)) . Я сапраўды думаю, што гэта проста таму, што гэта не чысты сінтаксіс для яго (ці, па меншай меры, ніхто не думаў, аднаго)
дададзена аўтар mgilson, крыніца
@MartijnPieters, Вы можаце патэнцыйна перафразаваць Спіс або набор або дыктуе разуменне з'яўляецца проста сінтаксічны цукар выкарыстоўваць выраз генератар ? Гэта выклікае блытаніну людзі, бачачы іх як <�я> эквівалент </я> азначае канец. Гэта тэхнічна не сінтаксічны цукар, як працэсы, на самай справе розныя, нават калі канчатковы прадукт такі ж.
дададзена аўтар jpp, крыніца
Спіс або ўсталяваць або дыктуе разуменне з'яўляецца толькі сінтаксічных выкарыстоўваць выраз генератара, які выводзіць вызначаны тып. <�Код> Спіс (я для г у (1, 2, 3)) гэты выраз генератар, які выводзіць спіс, SET (I для I ў (1, 2, 3)) </код > выводзіць набор. Ці азначае гэта, што сінтаксіс разумення не патрэбны? Магчыма, няма, але гэта вельмі зручна. Для тых рэдкіх выпадкаў, вам патрэбен картэж замест выраз генератара будзе рабіць, зразумела, і не патрабуе вынаходак іншы дужкі або кранштэйна.
дададзена аўтар Martijn Pieters, крыніца
@JKillian: розніца ёсць, але занадта тонкі для пераважнай большасці, каб клапаціцца аб. Гуляючы з итератора, як, што ў выразе без апрацоўкі StopIterator Выключэнне будзе дастаткова рэдка. :-)
дададзена аўтар Martijn Pieters, крыніца
@jpp: гэта ў <�я> каментар , а не ў маім адказе. Каментары, як правіла, не даступныя для рэдагавання. Тэхнічна я магу змяніць мой яшчэ, але толькі таму, што я мадэратар. І я стаю на мой каментар, так як * сінтаксіс вельмі блізка. Дэкаратары таксама сінтаксічны цукар, і іх рэалізацыя адрозніваецца істотным чынам ад сінтаксісу яны замянілі, так што гэта не адзінкавы прыклад. Я не перакананы, што адзін прыклад блытаніны складае агульную блытаніну.
дададзена аўтар Martijn Pieters, крыніца
@MartijnPieters Добры пытанне, хоць я наткнуўся на яго на другі дзень, спрабуючы напісаць свой уласны паштовы індэкс функцыі ў якасці практыкаванні, каб даведацца Python. Залішне казаць, што ён зблытаў чорт з мяне, чаму Картэж (ген ехр) не атрымаўся, але картэж ([генератарны ехр]) працаваў выдатна. У любым выпадку, добра, што ён адзначыў, што тут StopIteration будзе паглынутая генератарных выразаў/спасціжэння, але будзе распаўсюджвацца з спісу/набор/слоўнікавыя спасціжэння.
дададзена аўтар JKillian, крыніца
@MartijnPieters Хацеў бы адзначыць, што спіс (выраз генератар) не дакладна так жа, як [выраз] генератар : thecodingforums.com/threads/…
дададзена аўтар JKillian, крыніца
Адказ, відавочна, таму, што картэж сінтаксіс і круглыя ​​дужкі неадназначныя
дададзена аўтар Charles Salvia, крыніца
Розніца паміж выкарыстаннем разумення і выкарыстання канструктара + генератар з'яўляецца больш тонкім, калі вы клапоціцеся аб прадукцыйнасці. Спасціжэння прыводзяць да паскарэння будаўніцтва ў параўнанні з выкарыстаннем генератара перадаецца ў канструктар. У апошнім выпадку вы ствараеце і якое выконвае функцыі і функцыі з'яўляюцца дарагімі ў Python. <�Код> [рэч для рэчы ў рэчах] канструюе спіс значна хутчэй, чым (спіс рэчаў для рэчы ў рэчах) . Картэж разуменне не было б бескарысна; <�Код> картэж (рэч для рэчы ў рэчах) мае латэнтныя праблемы і картэж ([рэч для рэчы ў рэчах]) можа мець праблемы з памяццю.
дададзена аўтар Justin Turner Arthur, крыніца

Raymond Hettinger (адзін з асноўных распрацоўшчыкаў Python) быў гэта, каб сказаць пра картэжах ў нядаўні твіт :

<�Р> #python наканечніка: Як правіла, спісы для цыклаў; картэжы для структур. Спісы з'яўляюцца аднароднымі; картэжы heterogeneous.Lists для зменнай даўжыні. </р>

Гэта (для мяне) падтрымлівае ідэю, што калі элементы ў паслядоўнасці звязаны дастаткова, каб быць роджанае, добра, генератар, то ён павінен быць спісам. Хоць картэж ітэрацыі і здаецца, што проста ў няўхільнай спісе, гэта сапраўды Python эквівалент C структуры:

struct {
    int a;
    char b;
    float c;
} foo;

struct foo x = { 3, 'g', 5.9 };

становіцца ў Python

x = (3, 'g', 5.9)
52
дададзена
Там таксама агульны выпадак, калі вы выкарыстоўваеце генератар для стварэння структуры, як рэчы: дзе вы апрацоўка тэкставых запісаў, такіх як CSV. Гэта часта пішацца line_values ​​= картэж (Int (x.trim ()) для х у line.split ( '')) . Як ужо адзначалася, з дапамогай канструктара картэжа тут замест разумення ўплывае на прадукцыйнасць і аналіз вялікіх масіваў дадзеных гэтага тыпу з'яўляецца выпадак, калі вы сапраўды клапаціцца аб прадукцыйнасці.
дададзена аўтар Tom, крыніца
Ўласцівасць immutibility можа быць важным, хоць і часта добрая нагода, каб выкарыстоўваць картэж, калі вы звычайна карыстаецеся спіс. Напрыклад, калі ў вас ёсць спіс з 5 нумароў, якія вы хочаце выкарыстоўваць у якасці ключа да слоўнікі, то картэж шлях.
дададзена аўтар pavon, крыніца
@ Dave Вы можаце, верагодна, проста выкарыстоўваць operator.itemgetter у гэтым выпадку.
дададзена аўтар chepner, крыніца
То добры савет ад Raymond Хеттингер. Я б яшчэ сказаць, што ёсць выпадак выкарыстання з дапамогай канструктара картэжа з генератарам, напрыклад, распакаванне іншай структуры, можа быць, больш, у меншы адзін пераборы ATTRS, што вы зацікаўлены ў пераходзе на картэж запіс.
дададзена аўтар dave, крыніца
@chepner, я бачу. Гэта даволі блізка да таго, што я маю на ўвазе. Ён сапраўды вяртаецца выкліканым так, калі мне трэба зрабіць гэта толькі адзін раз, я не бачу шмат перамог супраць толькі з дапамогай картэж (OBJ [ITEM] для пункта ў штуках) непасрэдна. У маім выпадку я ўбудаванне гэта ў спісе разуменне, каб зрабіць спіс картэжаў запісаў. Калі мне трэба зрабіць гэта некалькі разоў у кодзе, то itemgetter выглядае пышна. Магчыма itemgetter б больш ідыёматычны так ці інакш?
дададзена аўтар dave, крыніца
Я бачу сувязь паміж frozenset і ўсталяваць аналагічна картэж і спіс. Гэта менш пра гетэрагеннасць і больш пра нязменнасці - frozensets і картэжы могуць быць ключы да слоўніках, спісы і наборы не могуць з-за іх зменлівасцю.
дададзена аўтар polyglot, крыніца

Since Python 3.5, you can also use unpacking syntax for a tuple comprehension:

*(x for x in range(10)),
22
дададзена
Гэта выдатна (і гэта працуе), але я не магу знайсці дзе гэта дакументальна! У вас ёсць спасылка?
дададзена аўтар felixphew, крыніца
дададзена аўтар czheo, крыніца

Зразуменне працуе перакручванне або ітэрацыі па пунктах і прызначаючы іх у кантэйнер, картэж не можа атрымліваць задання.

Пасля таго, як Картэж будзе створаны, ён не можа быць дададзены, пашыраны, або прызначаны. Адзіны спосаб змяніць картэж, калі адзін з яго аб'ектаў самі па сабе можа быць прызначаныя (не з'яўляецца картэж кантэйнера). Паколькі Картэж толькі трымае спасылку на гэты від аб'екта.

Таксама - картэж мае свой уласны канструктар картэж() , які вы можаце даць любой итератор. Гэта азначае, што для стварэння картэжа, вы можаце зрабіць:

tuple(i for i in (1,2,3))
18
дададзена
У пэўным сэнсе я згодны (пра гэта не з'яўляецца неабходным, таму што спіс будзе рабіць), але ў іншых адносінах я не згодны (пра разумная істота, таму што гэта нязменная). У пэўным сэнсе, гэта мае сэнс мець разуменне для нязьменных аб'ектаў. які робіць LST = [х для й у ...]; x.append() ?
дададзена аўтар mgilson, крыніца
@mgilson, калі картэж з'яўляецца нязменным, што азначае базавую рэалізацыю <�я> не магу </я> «генераваць» картэж ( «пакаленне», маючы на ​​ўвазе будынак адзін кавалак за адзін раз). нязменная азначае, што вы не можаце пабудаваць адзін з 4-х частак, змяняючы адзін з 3-х штук. замест гэтага, вы рэалізуеце картэж «пакаленне» шляхам стварэння спісу, то, прызначанае для генерацыі, а затым пабудаваць картэж у якасці апошняга кроку, і адмовіцца ад спісу. Мова адлюстроўвае гэтую рэальнасць. Падумайце картэжы як C структуры.
дададзена аўтар Scott, крыніца
хоць было б разумна сінтаксічны цукар спасціжэння працаваць для картэжаў, так як вы не можаце выкарыстоўваць картэж, пакуль разуменне не вяртаюцца. Эфектыўна яно не дзейнічае як змяняемыя, а картэж разуменне можа паводзіць сябе так жа, як трэба далучыць да радок.
дададзена аўтар uchuugaka, крыніца
@mgilson Я не ўпэўнены, як гэта адносіцца да таго, што я сказаў?
дададзена аўтар Inbar Rose, крыніца

Маё меркаванне, што яны выбеглі з дужак і не думаюць, што гэта будзе дастаткова карыснай для warrent дадання «пачварны» сінтаксісу ...

11
дададзена
@uchuugaka - Не зусім. Яны выкарыстоўваюцца для аператараў параўнання. Гэта, верагодна, можа ўсё яшчэ быць зроблена без двухсэнсоўнасці, але, магчыма, не варта намаганняў ...
дададзена аўтар mgilson, крыніца
Верагодна 3.5: python.org/dev/peps/pep-0448
дададзена аўтар mgilson, крыніца
Не працуе ў 2.7.10
дададзена аўтар uchuugaka, крыніца
Якая версія Python з'яўляецца тое, што павінна працаваць у?
дададзена аўтар uchuugaka, крыніца
Абсалютна агідны. Мне гэта падабаецца, але толькі таму, што ён хворы невыразны матэрыял. Ніхто ніколі не павінен выкарыстоўваць. Высокі.
дададзена аўтар uchuugaka, крыніца
Не, гэта зусім іншае. Граматыка мовы вельмі спецыфічны аб тых, як знакі. Яны маюць вельмі выразную сэнсавую і лексічную вобласць бачнасці, якая была б адназначная (ці амаль дастаткова, каб прымусіць яго працаваць з невялікімі зменамі), калі ўжываюцца таксама да новых лексемы, як існуе для іншых дужак. Паренс ўжо выкарыстоўваецца для размежавання сферы шмат розных рэчаў, так што гэта павінна быць вельмі і вельмі выканальна. Калі б гэта было толькі тое, што хтосьці вырашыў. Шчыра кажучы, наборам таксама патрэбныя літаральна любоў і спасціжэння павінны атрымаць сигил.
дададзена аўтар uchuugaka, крыніца
Вуглавыя дужкі невыкарыстоўваныя.
дададзена аўтар uchuugaka, крыніца
@uchuugaka Варта адзначыць, што {* ()} , хоць непрыгожа, працуе як пустое мноства літаральнага!
дададзена аўтар M. I. Wright, крыніца

У якасці іншага плаката MACM згадвалася, самы хуткі спосаб стварыць картэж з генератара картэж ([генератар]) .


параўнанне прадукцыйнасці

  • List comprehension:

    $ python3 -m timeit "a = [i for i in range(1000)]"
    10000 loops, best of 3: 27.4 usec per loop
    
  • Tuple from list comprehension:

    $ python3 -m timeit "a = tuple([i for i in range(1000)])"
    10000 loops, best of 3: 30.2 usec per loop
    
  • Tuple from generator:

    $ python3 -m timeit "a = tuple(i for i in range(1000))"
    10000 loops, best of 3: 50.4 usec per loop
    
  • Tuple from unpacking:

    $ python3 -m timeit "a = *(i for i in range(1000)),"
    10000 loops, best of 3: 52.7 usec per loop
    

My version of python:

$ python3 --version
Python 3.6.3

Такім чынам, вы заўсёды павінны стварыць картэж з спісу разумення, калі прадукцыйнасць не з'яўляецца праблемай.

6
дададзена

Картэж не можа эфектыўна быць дададзены як спіс.

Так картэж разуменню трэба будзе выкарыстоўваць спіс ўнутры, а затым пераўтварыць у картэж.

Гэта было б тое ж самае, што вы робіце зараз: картэж ([разуменне])

3
дададзена

Я лічу, што гэта проста дзеля яснасці, мы не хочам, каб загрувашчваць мову з занадта шмат розных сімвалаў. Таксама картэж разуменне ніколі не неабходна , спіс проста можа быць выкарыстаны замест з нязначнымі адрозненнямі хуткасці, у адрозненне ад Dict разумення, у адрозненне ад спісу разумення.

2
дададзена
Пачынаючы ўсе вашыя каментары з «няма, вы не правы» не зробіць вас правільна. Чытаць @ паведамленняў jemidiah зноў, ён мае кропку.
дададзена аўтар Evyatar Meged, крыніца
@jemidiah Не, вы памыляецеся. Гэта не абавязкова. Вы лёгка можаце проста зрабіць картэж (х для х у у) замест таго, каб яна ўбудаваная ў мову, што даказвае, што гэта не патрэбна.
дададзена аўтар jamylak, крыніца
@jemidiah Няма вы ілжывыя. Вы спрачаліся пра што-то цалкам не звязаныя. Не саромейцеся выкарыстоўваць картэжы, калі вы хочаце, вы можаце проста атрымаць свой картэж без картэжа разумення. Я нават не ведаю, пра што вы кажаце. Проста пераўтварыць спіс разуменне ў картэж або ўсё, што вам трэба. Давайце трымаць пітон простага, нам не патрэбныя картэжы спасціжэння яны не з'яўляюцца неабходнымі. Ці не дадавайце вялікае значэнне, і гэта важаць ад кошту супраць робіць мову больш складаным. Не ператварайце пітона ў Perl прыяцелю
дададзена аўтар jamylak, крыніца
Абодва вы зноў чытаць мае паведамленні: P
дададзена аўтар jamylak, крыніца
@jemidiah Я не ўпэўнены, Evyatar сказаў мне
дададзена аўтар jamylak, крыніца
Неабходнасць: спісы unhashable, картэжы hashable. (Вось чаму я гугл гэтай старонкі.)
дададзена аўтар jemidiah, крыніца
@jamylak: Гэта непрадуктыўна, так што я не буду рэагаваць далей - не саромейцеся, каб атрымаць апошняе слова, калі вы хочаце. Тым не менш, я не магу не адзначыць, што, нягледзячы на ​​тое, што вы толькі што сказалі, Evyatar не сказаць вам, каб спытаць мяне, каб прачытаць ваш пост яшчэ раз. Ён сказаў <�я> вы , каб зноў прачытаць мой пост і нічога не сказаў пра тое, што мяне нічога рабіць.
дададзена аўтар jemidiah, крыніца
@jamylak: чаму вы пытаецеся мяне чытаць ваш пост яшчэ раз? Я ўжо адказаў на самай апошняй. Гэта якая трапляе дзіўна.
дададзена аўтар jemidiah, крыніца
Я не ўпэўнены, што сказаць. Я адчуваю, што я ўжо даволі ясна, і вы робіце гэта абмеркаванне даволі эмацыйны, так што здаецца, наўрад ці будзе карысна працягнуць.
дададзена аўтар jemidiah, крыніца
Я не казаў, што не было ніякай абыходны шлях для «картэж спасціжэння" - відавочна, ёсць, і гэта літаральна прыняты адказ. Я адказваў на ваша заяву, што «спіс толькі можа быць выкарыстаны замест», што няправільна. Напрыклад, вы не можаце выкарыстоўваць спіс у якасці ключа ў Слоўніку. Гэта сапраўды неабходна выкарыстоўваць «картэж разуменне» (або абыходны шлях) часам. (Акрамя таго, старая нітка!)
дададзена аўтар jemidiah, крыніца

Дужкі не ствараюць картэж. ён жа адзін = (два), не з'яўляецца картэжам. Адзіны спосаб абыйсці гэта альбо адзін = (два,) або адзін картэж = (два). Такім чынам, рашэнне:

tuple(i for i in myothertupleorlistordict) 
1
дададзена
прыемна. гэта амаль тое ж самае.
дададзена аўтар uchuugaka, крыніца

Мы можам генерыраваць картэжы з спісу разумення. Наступны адзін дадае два ліку паслядоўна ў картэж і дае спіс з лічбаў 0-9.

>>> print k
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99]
>>> r= [tuple(k[i:i+2]) for i in xrange(10) if not i%2]
>>> print r
[(0, 1), (2, 3), (4, 5), (6, 7), (8, 9)]
1
дададзена