Python liste dilimiyle atama nasıl çalışır?


102

Python doc, bir listeyi dilimlemenin yeni bir liste döndürdüğünü söylüyor.
Şimdi "yeni" bir liste döndürülüyorsa "Dilimlere atama" ile ilgili aşağıdaki sorularım var

a = [1, 2, 3]
a[0:2] = [4, 5]
print a

Şimdi çıktı:

[4, 5, 3] 
  1. Bir şeyi geri döndüren bir şey, ifadenin sol tarafına nasıl gelebilir?
  2. Evet, dokümanları okudum ve bunun mümkün olduğunu söylüyor, şimdi bir listeyi dilimlemek "yeni" bir liste döndürdüğüne göre, orijinal liste neden değiştiriliyor? Arkasındaki mekaniği anlayamıyorum.

@Mark Longair üzgünüm, çıktının değil sadece kodun biçimlendirilmesi gerektiğini düşündüm
Kartik Anand


7
Ne yapacağını anlıyor musun a[0] = 4?
Josh Lee

1
@KartikAnand Slice ataması, yeni bir listenin oluşturulmadığı özel bir senaryodur. Bir nesnenin sol tarafında ad bağlaması olmadan bir nesne oluşturmak mantıklı değildir =, bu nedenle bunu geçersiz sözdizimi olarak atmak yerine, python onu beklediğiniz gibi bir şeye dönüştürür. Python'un referansları olmadığından, bir dilim sonucunun orijinal listeyi değiştirmesi işe yaramaz. Bir kopya alırsın. Başvurunuz hakkında daha fazla bilgi verdiyseniz, işleri 'pitonik' şekilde yapmanıza daha iyi yardımcı olabiliriz. :)
Casey Kuball

1
@Darthfett Şu anda herhangi bir uygulama üzerinde çalışmıyorum, ellerimi kirletmeye başlamadan önce kendi kendime python öğretiyorum :)
Kartik Anand

Yanıtlar:


117

Çok benzer sözdizimi kullanan iki farklı işlemi karıştırıyorsunuz:

1) dilimleme:

b = a[0:2]

Bu, diliminin bir kopyasını oluşturur ave ona atar b.

2) dilim ataması:

a[0:2] = b

Bu değiştirir dilim aiçeriğiyle b.

Sözdizimi benzer olsa da (tasarım gereği hayal ediyorum!), Bunlar iki farklı işlemdir.


4
Benim şüphem bu, ikinci durumda, neden a dilimi yeni bir liste değil ??
Kartik Anand

12
@KartikAnand Çünkü öyle değil. Dilin belirttiği bu değil.
Marcin

Açık olmak gerekirse, "bir dilim alır" aslında "bir dilimin kopyasını yapmak" anlamına gelir ki bu da karışıklığın bir kısmının geldiği yerdir.
Mark Ransom

2
@KartikAnand: Temelde evet. Tercüman hangisinin hangisi olduğunu bilir ve bunları uygun şekilde ele alır.
NPE

1
@Dubslow: Bunu itertools modülünü kullanarak yapabilirsiniz . Davanızı için fonksiyon kullanmak islice ile start=1, stop=None. Bu, herhangi bir kopyadan kaçınacak ve tembel değerlendirme kullanacaktır (sizin durumunuzda orijinal listeye tembel erişim).
Spiros

69

Belirttiğiniz zaman asol tarafındaki =operatör, sen Python'un kullandığınız normal bir atama adını değiştirir, ayeni değere noktasına geçerli bağlamda. Bu a, işaret ettiği önceki değeri değiştirmez .

Operatörün a[0:2]sol tarafında belirterek , =Python'a Dilim Atamasını kullanmak istediğinizi söylüyorsunuz . Dilim Atama, bir listeden içerik ekleyebileceğiniz, silebileceğiniz veya değiştirebileceğiniz listeler için özel bir sözdizimidir:

Yerleştirme :

>>> a = [1, 2, 3]
>>> a[0:0] = [-3, -2, -1, 0]
>>> a
[-3, -2, -1, 0, 1, 2, 3]

Silme :

>>> a
[-3, -2, -1, 0, 1, 2, 3]
>>> a[2:4] = []
>>> a
[-3, -2, 1, 2, 3]

Değiştirme :

>>> a
[-3, -2, 1, 2, 3]
>>> a[:] = [1, 2, 3]
>>> a
[1, 2, 3]

Not:

Dilimin uzunluğu, atanan dizinin uzunluğundan farklı olabilir, dolayısıyla hedef dizi izin veriyorsa hedef dizinin uzunluğunu değiştirebilir. - kaynak

Dilim Atama, Tuple Unpacking'e benzer bir işlev sağlar . Örneğin a[0:1] = [4, 5], şuna eşdeğerdir:

# Tuple Unpacking
a[0], a[1] = [4, 5]

Tuple Unpacking ile sıralı olmayan listeleri değiştirebilirsiniz:

>>> a
[4, 5, 3]
>>> a[-1], a[0] = [7, 3]
>>> a
[3, 5, 7]

Bununla birlikte, öğeleri ekleyemeyeceğiniz veya çıkaramayacağınız için paket açma, değiştirme ile sınırlıdır.

Tüm bu işlemlerden önce ve sonra aaynı liste. Python, bir listeyi yerinde değiştirmek için güzel sözdizimsel şeker sağlar.


6
Benzer, ancak aynı değil, çünkü solda ve sağda eşit olmayan sayıda öğeye sahip olabilirsiniz.
Mark Ransom

@MarkRansom Bu harika bir nokta, bunu açıklığa kavuşturmak için daha fazla bilgi ekledim.
Casey Kuball

2
a[:] = some_listdenk a = some_list[:]ya a = some_list?
jadkik94

2
@ jadkik94 Ne. a[:] = some_list'nın her unsurunu ait aolduğu şekilde ayarlar some_list. Bahsettiğiniz herhangi birini yapmak, olanı değiştirir a. Örneğin: a = [1, 2, 3] b = a a[:] = [4, 5, 6] a is b. Son satır, adeğerini değiştirmek yerine değerini değiştirirse False olur .
Casey Kuball

@CaseyKuball start: stop: stepDilim atama yaparken değeri her zaman pozitif olmalı mı ?
forvet

26

Aynı soruyla daha önce karşılaştım ve bu, dil spesifikasyonu ile ilgili. Göre atama-tabloların ,

  1. Atamanın sol tarafı abonelik ise, Python __setitem__bu nesneyi çağıracaktır . a[i] = xeşdeğerdir a.__setitem__(i, x).

  2. Atamanın sol tarafı dilim ise, Python da çağıracaktır __setitem__, ancak farklı argümanlarla: a[1:4]=[1,2,3]eşdeğerdir a.__setitem__(slice(1,4,None), [1,2,3])

Bu nedenle '=' işaretinin sol tarafındaki liste dilimi farklı davranır.


4

Bir atama işleminin sol tarafını dilimleyerek, hangi öğelerin atanacağını belirlersiniz.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.