Sorulan Soruya Nerede Cevap Vereceğim
Python neden onu kutudan çıkarmıyor?
Bunun Python Zen ile ilgisi olduğundan şüpheleniyorum : "Bunu yapmanın bir - ve tercihen tek - açık bir yolu olmalı." Bu, sözlüklerden değerlere erişmek için iki belirgin yol oluşturur: obj['key']
ve obj.key
.
Uyarılar ve Tuzaklar
Bunlar, kodda olası netlik ve karışıklık eksikliğini içerir. yani, kodunuzu daha sonraki bir tarihte tutacak bir başkası , hatta bir süreliğine tekrar girmiyorsanız bile sizin için kafa karıştırıcı olabilir . Yine Zen'den : "Okunabilirlik önemlidir!"
>>> KEY = 'spam'
>>> d[KEY] = 1
>>> # Several lines of miscellaneous code here...
... assert d.spam == 1
Eğer d
örneği veya KEY
tanımlanır veya d[KEY]
uzak yerden atanır d.spam
kullanılıyor bu yaygın-el deyim olmadığından, kolayca, yapılıyor neler olup karışıklığa yol açabilir. Beni şaşırtma potansiyeline sahip olacağını biliyorum.
Ayrıca, değerini KEY
aşağıdaki gibi değiştirirseniz (ancak değiştirmeyi özlüyorsanız d.spam
), şimdi şunu elde edersiniz:
>>> KEY = 'foo'
>>> d[KEY] = 1
>>> # Several lines of miscellaneous code here...
... assert d.spam == 1
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
AttributeError: 'C' object has no attribute 'spam'
IMO, çabaya değmez.
Diğer öğeler
Diğerlerinin de belirttiği gibi, herhangi bir yıkanabilir nesneyi (sadece bir dize değil) bir dikte anahtarı olarak kullanabilirsiniz. Örneğin,
>>> d = {(2, 3): True,}
>>> assert d[(2, 3)] is True
>>>
yasal, ancak
>>> C = type('C', (object,), {(2, 3): True})
>>> d = C()
>>> assert d.(2, 3) is True
File "<stdin>", line 1
d.(2, 3)
^
SyntaxError: invalid syntax
>>> getattr(d, (2, 3))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: getattr(): attribute name must be string
>>>
değil. Bu, sözlük anahtarlarınız için bir nesne özelliğine erişirken sahip olmadığınız tüm yazdırılabilir karakterlere veya diğer yıkanabilir nesnelere erişmenizi sağlar. Bu, Python Yemek Tarifleri'nden (Ch.9) tarif gibi önbelleğe alınmış bir nesne metasınıfı gibi büyüyü mümkün kılar .
Nerede Editörlük Yaparım
spam.eggs
Üzerinde estetiği tercih ediyorum spam['eggs']
(sanırım daha temiz görünüyor) ve gerçekten tanıştığımda bu işlevselliği özlemeye başladım namedtuple
. Ancak aşağıdakileri yapabilmenin rahatlığı onu gölgede bırakır.
>>> KEYS = 'spam eggs ham'
>>> VALS = [1, 2, 3]
>>> d = {k: v for k, v in zip(KEYS.split(' '), VALS)}
>>> assert d == {'spam': 1, 'eggs': 2, 'ham': 3}
>>>
Bu basit bir örnek, ama sık sık kendimi obj.key
gösterim kullanacağımdan farklı durumlarda dikte kullanarak buluyorum (yani, bir XML dosyasından tercihleri okumam gerektiğinde). Dinamik bir sınıf oluşturmaya ve estetik nedenlerle bazı özellikleri atlatmaya çalıştığım diğer durumlarda, okunabilirliği artırmak için tutarlılık için bir diksiyon kullanmaya devam ediyorum.
Eminim OP uzun zamandır bunu tatmin edici bir şekilde çözmüştür, ancak yine de bu işlevselliği istiyorsa, bunu sağlayan pypi'den paketlerden birini indirmenizi öneririm:
Demet daha aşina olduğum kişi. Alt sınıfdict
, böylece tüm bu işlevselliğe sahip olursunuz.
AttrDict o da oldukça iyi, ama onunla aşina olduğu değilim ve sahip olduğu kadar ayrıntılı olarak kaynağına baktım değil gibi de görünüyor Bunch .
- Bağımlı Aktif olarak korunur ve attr benzeri erişim ve daha fazlasını sağlar.
- Rotareti'nin yorumlarında belirtildiği gibi, Bunch kullanımdan kaldırıldı, ancak Munch adında aktif bir çatal var .
Ancak, onun kodun okunabilirliği artırmak için şiddetle o tavsiye değil onun notasyonu stilleri karıştırın. Bu gösterimi tercih ederse, sadece dinamik bir nesneyi başlatmalı, ona istenen niteliklerini eklemeli ve bir gün olarak adlandırmalıdır:
>>> C = type('C', (object,), {})
>>> d = C()
>>> d.spam = 1
>>> d.eggs = 2
>>> d.ham = 3
>>> assert d.__dict__ == {'spam': 1, 'eggs': 2, 'ham': 3}
Güncelleme Yaptığımda, Yorumlardaki Takip Sorusunu Yanıtlamak İçin
Yorumlarda (aşağıda), Elmo soruyor:
Ya daha derine inmek istersen? (tipe (...) göre)
Bu kullanım durumunu hiç kullanmadım (yine de, dict
tutarlılık için iç içe kullanma eğilimindeyim ), aşağıdaki kod çalışıyor:
>>> C = type('C', (object,), {})
>>> d = C()
>>> for x in 'spam eggs ham'.split():
... setattr(d, x, C())
... i = 1
... for y in 'one two three'.split():
... setattr(getattr(d, x), y, i)
... i += 1
...
>>> assert d.spam.__dict__ == {'one': 1, 'two': 2, 'three': 3}
collections.namedtuple
bunun için çok faydalıdır.