Python'da tuple vs tuple ne zaman kullanılır?


31

Akılda belirli bir örnek dosya adlarının ve boyutlarının bir listesidir. Listedeki her bir öğenin biçiminde mi {"filename": "blabla", "size": 123}, yoksa sadece mı olduğuna karar veremiyorum ("blabla", 123). Bir sözlük bana daha mantıklı geliyor, çünkü boyuta erişmek, örneğin ... ' file["size"]dan daha açıklayıcı file[1]... ama gerçekten emin değilim. Düşünceler?


Bir zeyilname olarak, tupleların okunabilirliği konusunda endişeleriniz varsa - verilerin yukarıdaki bağlantınız olduğu yerlerde, bunun yerine kullanacağınız ve onunla değiştirileceği durumlarda , tuple açmayı düşünün . Elbette bu iyi bir belgeye dayanır. fname, file_size = filefile[1]file_size
nlsdfnbch

2
Hangi veri yapısını oluşturduğunuza ve nasıl erişmeyi planladığınıza bağlı. (dosya adına göre? indeksine göre? ikisi de?) Yapının bir sırayı hatırlaması gerekiyor mu; boyut listesini sıralamak mı yoksa konuma göre mi erişmek istiyorsunuz (örn. "en büyük / en küçük dosyalar")? Bunlara bağlı olarak, 'en iyi' cevap dikte, OrderedDict, namedtuple, sade eski liste veya kendinize ait özel bir sınıf olabilir. Sizden daha fazla içeriğe ihtiyacınız var.
smci

Yanıtlar:


78

Ben kullanırdım namedtuple:

from collections import namedtuple
Filesize = namedtuple('Filesize', 'filename size')
file = Filesize(filename="blabla", size=123)

Şimdi file.sizeve file.filenameIMHO en okunabilir form olan programınızda kullanabilirsiniz . Not namedtupletote gibi değişmez nesneler yaratır ve burada tarif edildiği gibi sözlüklerden daha hafiftirler .


1
Teşekkürler, iyi fikir, bugünden önce hiç duymadım (Python'da oldukça çekiciyim). Soru: Kodun herhangi bir yerinde birileri aynı "sınıfı" tanımladıysa, muhtemelen biraz farklı bir biçimde ne olur? örneğin, başka bir kaynak dosyasında, iş arkadaşı Bob vardıFilesize = namedtuple('Filesize', 'filepath kilobytes')
user949300

Ayrıca, çok güzel bir attrsmodül de kullanabilirsiniz (onu bulabilir pipya da sadece arayabilirsin), bu da adlandırılmış tuple için çok benzer sözdizimsel kolaylıklara sahip olmanıza izin verir, ancak size değişkenlik verebilir (ama değiştirilemez hale getirilebilir). Başlıca fonksiyonel fark, yapılan attrssınıfların düz tuplelere eşit şekilde karşılaştırılmadıklarıdır namedtuple.
mtraceur

3
@DocBrown Python'un hiçbir beyannamesi yoktur. class, defve =tümü yalnızca önceki kullanımların üzerine yazar. repl.it
Challenger5

@ Challenger5: haklısın, benim hatam, bu yüzden doğru cevap: en son tanım sayılır, Python çalışma zamanından hiçbir hata gelmez, fakat diğer değişkenlerde olduğu gibi benzer davranış.
Doktor Brown,

8
Bunun namedtupleasılsız özelliklere sahip yeni bir tür için kısa bir el ilanı olduğunu unutmayın . Bu, cevabın etkili olduğu anlamına gelir; "Ne bir tuplene de bir dict, ne bir object." +1
jpmc26

18

{"dosya adı": "blabla", "boyut": 123} veya sadece ("blabla", 123)

Bu, biçim / şemanızı bant içi veya bant dışı kodlamanızın eski sorusu.

Verilerin biçimini doğrudan verilerde ifade etmekten kaynaklanan okunabilirliği ve taşınabilirliği elde etmek için biraz bellek takas edersiniz. Bunu yapmazsanız, ilk alanın dosya adı, ikincisi ise boyutun başka yerde tutulması gerektiği bilgisidir. Bu bellek tasarrufu sağlar, ancak okunabilirlik ve taşınabilirlik maliyeti. Hangi şirketinize daha fazla paraya mal olacak?

Değişmez konuya gelince, değişmezliğin değişim karşısında işe yaramaz anlamına gelmediğini unutmayın. Bu, daha fazla bellek kapmamız, bir kopyadaki değişikliği yapmamız ve yeni kopyayı kullanmamız gerektiği anlamına gelir. Bu ücretsiz değil, ancak genellikle bir anlaşma kırıcı değil. Her zaman bir şeyleri değiştirmek için değişmez dizeleri kullanırız.

Diğer bir husus, genişletilebilirliktir. Verileri yalnızca konumsal olarak, format bilgisini kodlamadan sakladığınızda, o zaman yalnızca tek bir mirasa mahkum edilirsiniz; bu, kurulan alanlardan sonra ek alanları birleştirme pratiklerinden başka bir şey değildir. Üçüncü bir alanı oluşturma tarihi olarak tanımlayabilirim ve yine birinci ve ikinci aynı şekilde tanımladığımdan beri formatınızla uyumlu olabilirim.

Bununla birlikte, yapamadığım şey, birbiriyle örtüşen bazı alanları olan, bazıları olmayan, bunları bir biçimde saklayan ve yalnızca bir veya diğer biçimler hakkında bilenler için yararlı olan iki bağımsız olarak tanımlanmış biçimi bir araya getirmektir.

Bunu yapmak için, başlangıçtaki format bilgisini kodlamam gerekiyor. "Bu alanın dosya adı" demeliyim. Bunu yapmak çoklu kalıtıma izin verir.

Muhtemelen mirasa yalnızca nesneler bağlamında ifade edilmekle kalıyorsunuz, fakat aynı fikirler veri formatları için çalışıyor, çünkü nesneler veri formatlarında saklanıyor. Bu tamamen aynı problem.

İhtiyacınız en fazla hangisi olduğunu düşündüğünüzü kullanın. Olmaması için iyi bir neden gösteremediğim sürece esnekliğe ulaşırım.


3
Dürüst olmak gerekirse, bant içi veya bant dışı bir format kullanmak arasında emin olmayan herkesin bant dışı bir format kullanması gerekecek kadar sıkı performans gereksinimleri olduğundan şüpheliyim
Alexander - Reinstate Monica

2
@Alexander çok doğru. İnsanlara bu konuda öğretmeyi tercih ediyorum, böylece bant dışı çözümlerle karşılaştıklarında neye baktıklarını anlıyorlar. İkili formatlar genellikle bunu şaşırtma nedenleriyle yapar. Herkes taşınabilir olmak istemez. Performans nedenleriyle ilgili olarak, gerçekten önemliyse, bant dışı kalmadan önce sıkıştırmayı düşünün.
candied_orange

OP’nin Python kullandığını unutmayın, bu nedenle performans konusunda pek endişelenmiyorlar. Çoğu üst düzey kod ilk önce okunabilirlikle yazılmalıdır; erken optimizasyon tüm kötülüklerin kökenidir.
Dağevleri

@Dagrooms Python'da nefret etmiyor. Birçok durumda iyi performans gösterir. Ama aksi halde söylediğiniz her şeye katılıyorum. Demek istediğim "Bu yüzden insanlar böyle yapıyor. İşte bu yüzden umursamıyorsun" demekti.
candied_orange

@CandiedOrange Dilden nefret etmiyorum, günlük çalışmamda kullanıyorum. İnsanların kullanma şeklini beğenmedim.
Dağevleri

7

İki özelliğe sahip bir sınıf kullanırdım. file.sizeya file[1]da ikisinden daha güzel file["size"].

Basit, karmaşıktan daha iyidir.


Durumda birinin merak olduğunu: üreten JSONs için, her iki çalışma eşit derecede iyi: file = Filesize(filename='stuff.txt', size=222)ve filetup = ("stuff.txt", 222)her ikisi de aynı JSON oluşturmak: json.dumps(file)ve json.dumps(filetup)sonucu:'["stuff.txt", 222]'
Juha Untinen

5

Dosya adları benzersiz mi? Öyleyse, listeyi tamamen silebilir ve tüm dosyalar için yalnızca bir sözlük kullanabilirsiniz. örneğin (varsayımsal bir web sitesi)

{ 
  "/index.html" : 5467,
  "/about.html" : 3425,
  "/css/main.css" : 9876
}

vb...

Şimdi, "isim" ve "boyut" alamazsınız, sadece anahtar ve değeri kullanırsınız, ancak bu genellikle daha doğaldır. YMMV.

Eğer varsa gerçekten netlik için bir "boyut" istiyorsun yoksa o zaman dosya için birden fazla değer gerekir:

{ 
   "/index.html" : { "size": 5467, "mime_type" : "foo" },
   "/about.html" : { "size": 3425, "mime_type" : "foo" }
   "/css/main.css" : { "size": 9876, "mime_type" : "bar" }
}

0

Python'da, sözlük değişken nesnedir. Diğer taraf, demet değişmez nesnedir.

Sözlük anahtarını değiştirmeniz gerekirse, sık sık veya her seferinde değer çifti. kullanılacak sözlük öneririm.

Eğer sabit / statik verileriniz varsa, kullanacağınız dizgeri öneririm.

# dictionary define.
a = {}
a['test'] = 'first value'

# tuple define.
b = ()
b = b+(1,)

# here, we can change dictionary value for key 'test'
a['test'] = 'second'

Ancak, atama operatörünü kullanarak tuple verilerini değiştiremezsiniz.

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.