Considere as seguintes expressões. Observe que algumas expressões são repetidas para apresentar o "contexto".
(esta é uma longa lista)
a, b = 1, 2 # simple sequence assignment
a, b = ['green', 'blue'] # list asqignment
a, b = 'XY' # string assignment
a, b = range(1,5,2) # any iterable will do
# nested sequence assignment
(a,b), c = "XY", "Z" # a = 'X', b = 'Y', c = 'Z'
(a,b), c = "XYZ" # ERROR -- too many values to unpack
(a,b), c = "XY" # ERROR -- need more than 1 value to unpack
(a,b), c, = [1,2],'this' # a = '1', b = '2', c = 'this'
(a,b), (c,) = [1,2],'this' # ERROR -- too many values to unpack
# extended sequence unpacking
a, *b = 1,2,3,4,5 # a = 1, b = [2,3,4,5]
*a, b = 1,2,3,4,5 # a = [1,2,3,4], b = 5
a, *b, c = 1,2,3,4,5 # a = 1, b = [2,3,4], c = 5
a, *b = 'X' # a = 'X', b = []
*a, b = 'X' # a = [], b = 'X'
a, *b, c = "XY" # a = 'X', b = [], c = 'Y'
a, *b, c = "X...Y" # a = 'X', b = ['.','.','.'], c = 'Y'
a, b, *c = 1,2,3 # a = 1, b = 2, c = [3]
a, b, c, *d = 1,2,3 # a = 1, b = 2, c = 3, d = []
a, *b, c, *d = 1,2,3,4,5 # ERROR -- two starred expressions in assignment
(a,b), c = [1,2],'this' # a = '1', b = '2', c = 'this'
(a,b), *c = [1,2],'this' # a = '1', b = '2', c = ['this']
(a,b), c, *d = [1,2],'this' # a = '1', b = '2', c = 'this', d = []
(a,b), *c, d = [1,2],'this' # a = '1', b = '2', c = [], d = 'this'
(a,b), (c, *d) = [1,2],'this' # a = '1', b = '2', c = 't', d = ['h', 'i', 's']
*a = 1 # ERROR -- target must be in a list or tuple
*a = (1,2) # ERROR -- target must be in a list or tuple
*a, = (1,2) # a = [1,2]
*a, = 1 # ERROR -- 'int' object is not iterable
*a, = [1] # a = [1]
*a = [1] # ERROR -- target must be in a list or tuple
*a, = (1,) # a = [1]
*a, = (1) # ERROR -- 'int' object is not iterable
*a, b = [1] # a = [], b = 1
*a, b = (1,) # a = [], b = 1
(a,b),c = 1,2,3 # ERROR -- too many values to unpack
(a,b), *c = 1,2,3 # ERROR - 'int' object is not iterable
(a,b), *c = 'XY', 2, 3 # a = 'X', b = 'Y', c = [2,3]
# extended sequence unpacking -- NESTED
(a,b),c = 1,2,3 # ERROR -- too many values to unpack
*(a,b), c = 1,2,3 # a = 1, b = 2, c = 3
*(a,b) = 1,2 # ERROR -- target must be in a list or tuple
*(a,b), = 1,2 # a = 1, b = 2
*(a,b) = 'XY' # ERROR -- target must be in a list or tuple
*(a,b), = 'XY' # a = 'X', b = 'Y'
*(a, b) = 'this' # ERROR -- target must be in a list or tuple
*(a, b), = 'this' # ERROR -- too many values to unpack
*(a, *b), = 'this' # a = 't', b = ['h', 'i', 's']
*(a, *b), c = 'this' # a = 't', b = ['h', 'i'], c = 's'
*(a,*b), = 1,2,3,3,4,5,6,7 # a = 1, b = [2, 3, 3, 4, 5, 6, 7]
*(a,*b), *c = 1,2,3,3,4,5,6,7 # ERROR -- two starred expressions in assignment
*(a,*b), (*c,) = 1,2,3,3,4,5,6,7 # ERROR -- 'int' object is not iterable
*(a,*b), c = 1,2,3,3,4,5,6,7 # a = 1, b = [2, 3, 3, 4, 5, 6], c = 7
*(a,*b), (*c,) = 1,2,3,4,5,'XY' # a = 1, b = [2, 3, 4, 5], c = ['X', 'Y']
*(a,*b), c, d = 1,2,3,3,4,5,6,7 # a = 1, b = [2, 3, 3, 4, 5], c = 6, d = 7
*(a,*b), (c, d) = 1,2,3,3,4,5,6,7 # ERROR -- 'int' object is not iterable
*(a,*b), (*c, d) = 1,2,3,3,4,5,6,7 # ERROR -- 'int' object is not iterable
*(a,*b), *(c, d) = 1,2,3,3,4,5,6,7 # ERROR -- two starred expressions in assignment
*(a,b), c = 'XY', 3 # ERROR -- need more than 1 value to unpack
*(*a,b), c = 'XY', 3 # a = [], b = 'XY', c = 3
(a,b), c = 'XY', 3 # a = 'X', b = 'Y', c = 3
*(a,b), c = 'XY', 3, 4 # a = 'XY', b = 3, c = 4
*(*a,b), c = 'XY', 3, 4 # a = ['XY'], b = 3, c = 4
(a,b), c = 'XY', 3, 4 # ERROR -- too many values to unpack
Como deduzir corretamente o resultado de tais expressões manualmente?
a, *b = 1, 2, 3
tipo de desempacotamento. Mas isso é Py3k certo?Respostas:
Minhas desculpas pela extensão deste post, mas decidi optar pela completude.
Depois de conhecer algumas regras básicas, não é difícil generalizá-las. Vou fazer o meu melhor para explicar com alguns exemplos. Já que você está falando sobre avaliá-los "manualmente", vou sugerir algumas regras de substituição simples. Basicamente, você pode achar mais fácil entender uma expressão se todos os iteráveis estiverem formatados da mesma maneira.
Apenas para fins de desempacotamento, as seguintes substituições são válidas no lado direito do
=
(ou seja, para rvalues ):Se você descobrir que um valor não foi descompactado, você desfará a substituição. (Veja abaixo para mais explicações.)
Além disso, quando vir vírgulas "nuas", finja que há uma tupla de nível superior. Faça isso em ambos à esquerda e à direita (ou seja, para lvalues e rvalues ):
Com essas regras simples em mente, aqui estão alguns exemplos:
Aplicando as regras acima, nós convertemos
"XY"
a('X', 'Y')
, e cobrir as vírgulas nuas em parênteses:A correspondência visual aqui torna bastante óbvio como a tarefa funciona.
Aqui está um exemplo errado:
Seguindo as regras de substituição acima, temos o seguinte:
Isso é claramente errado; as estruturas aninhadas não combinam. Agora vamos ver como funciona para um exemplo um pouco mais complexo:
Aplicando as regras acima, obtemos
Mas agora está claro pela estrutura que
'this'
não será desempacotado, mas atribuído diretamente ac
. Portanto, desfazemos a substituição.Agora vamos ver o que acontece quando envolvemos
c
uma tupla:Torna-se
Novamente, o erro é óbvio.
c
não é mais uma variável simples, mas uma variável dentro de uma sequência e, portanto, a sequência correspondente à direita é descompactada em(c,)
. Mas as sequências têm um comprimento diferente, então há um erro.Agora, para desempacotamento prolongado usando o
*
operador. Isso é um pouco mais complexo, mas ainda é bastante simples. Uma variável precedida por*
torna-se uma lista, que contém todos os itens da sequência correspondente que não foram atribuídos a nomes de variáveis. Começando com um exemplo bastante simples:Isso se torna
A maneira mais simples de analisar isso é trabalhar a partir das extremidades.
'X'
é atribuído aa
e'Y'
é atribuído ac
. Os valores restantes na sequência são colocados em uma lista e atribuídos a elesb
.Valores como
(*a, b)
e(a, *b)
são apenas casos especiais dos anteriores. Você não pode ter dois*
operadores dentro de uma sequência lvalue porque seria ambíguo. Para onde iriam os valores em algo assim(a, *b, *c, d)
- emb
ouc
? Vou considerar o caso aninhado em um momento.Aqui, o erro é bastante autoexplicativo. O target (
*a
) deve estar em uma tupla.Isso funciona porque há uma vírgula nua. Aplicando as regras ...
Uma vez que não há variáveis além de
*a
,*a
engole todos os valores na sequência rvalue. E se você substituir o(1, 2)
por um único valor?torna-se
Novamente, o erro aqui é autoexplicativo. Você não pode desempacotar algo que não seja uma sequência e
*a
precisa de algo para desempacotar. Então, colocamos em uma sequênciaQual é equivalente a
Finalmente, este é um ponto comum de confusão:
(1)
é o mesmo que1
- você precisa de uma vírgula para distinguir uma tupla de uma instrução aritmética.Agora, para o aninhamento. Na verdade, este exemplo não estava em sua seção "ANINHADA"; talvez você não tenha percebido que estava aninhado?
Torna-se
O primeiro valor na tupla de nível superior é atribuído, e os valores restantes na tupla de nível superior (
2
e3
) são atribuídosc
- exatamente como deveríamos esperar.Já expliquei acima porque a primeira linha gera um erro. A segunda linha é boba, mas aqui está porque funciona:
Conforme explicado anteriormente, trabalhamos desde o início.
3
é atribuído ac
e, em seguida, os valores restantes são atribuídos à variável*
precedente, neste caso(a, b)
,. Isso é equivalente a(a, b) = (1, 2)
, o que funciona porque há o número certo de elementos. Não consigo pensar em nenhum motivo para isso aparecer no código funcional. Similarmente,torna-se
Trabalhar a partir das pontas,
's'
é atribuído ac
e('t', 'h', 'i')
é atribuído a(a, *b)
. Trabalhando novamente a partir das extremidades,'t'
é atribuído aa
e('h', 'i')
é atribuído a b como uma lista. Este é outro exemplo bobo que nunca deveria aparecer no código funcional.fonte
Acho a tupla do Python 2 descompactada muito simples. Cada nome à esquerda corresponde a uma sequência inteira ou a um único item em uma sequência à direita. Se os nomes corresponderem a itens únicos de qualquer sequência, deve haver nomes suficientes para cobrir todos os itens.
A descompactação prolongada, entretanto, pode certamente ser confusa, porque é muito poderosa. A realidade é que você nunca deve fazer os últimos 10 ou mais exemplos válidos que forneceu - se os dados forem assim estruturados, eles devem estar em uma
dict
ou uma instância de classe, e não em formas não estruturadas como listas.Claramente, a nova sintaxe pode ser abusada. A resposta à sua pergunta é que você não deveria ter que ler expressões como essa - são uma má prática e duvido que sejam usadas.
Só porque você pode escrever expressões arbitrariamente complexas, não significa que você deve. Você poderia escrever código como,
map(map, iterable_of_transformations, map(map, iterable_of_transformations, iterable_of_iterables_of_iterables))
mas não o faz .fonte
Eu acho que seu código pode ser enganoso, use outra forma para expressá-lo.
É como usar colchetes extras em expressões para evitar questões sobre a precedência dos operadores. É sempre um bom investimento para tornar seu código legível.
Eu prefiro usar a descompactação apenas para tarefas simples como a troca.
fonte