ในกรณีที่ฉันตอบคำถามที่ถูกถาม
ทำไมไพ ธ อนไม่เสนอมันนอกกรอบ?
ฉันสงสัยว่ามันเกี่ยวข้องกับZen of Python : "ควรมีอย่างใดอย่างหนึ่ง - และโดยเฉพาะอย่างยิ่งวิธีเดียวเท่านั้น - ชัดเจน" นี้จะสร้างสองวิธีที่เห็นได้ชัดกับค่าการเข้าถึงจากพจนานุกรม: และobj['key']
obj.key
Caveats และหลุมพราง
สิ่งเหล่านี้รวมถึงการขาดความชัดเจนและความสับสนในโค้ด กล่าวคือสิ่งต่อไปนี้อาจสร้างความสับสนให้กับบุคคลอื่นที่กำลังจะรักษารหัสของคุณในภายหลังหรือแม้แต่กับคุณหากคุณไม่ได้กลับไปใช้อีกสักพัก อีกครั้งจากZen : "ความสามารถในการอ่านมีค่า!"
>>> KEY = 'spam'
>>> d[KEY] = 1
>>> # Several lines of miscellaneous code here...
... assert d.spam == 1
หากd
มีการสร้างอินสแตนซ์หรือ KEY
ถูกกำหนดหรือ d[KEY]
ถูกกำหนดให้ห่างไกลจากจุดที่d.spam
มีการใช้งานมันสามารถนำไปสู่ความสับสนเกี่ยวกับสิ่งที่กำลังทำอยู่ได้อย่างง่ายดายเนื่องจากนี่ไม่ใช่สำนวนที่ใช้กันทั่วไป ฉันรู้ว่ามันจะมีศักยภาพที่จะทำให้ฉันสับสน
นอกจากนี้หากคุณเปลี่ยนค่าKEY
เป็นดังนี้ (แต่พลาดการเปลี่ยนแปลงd.spam
) ตอนนี้คุณจะได้รับ:
>>> 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 ไม่คุ้มกับความพยายาม
รายการอื่น ๆ
ดังที่คนอื่น ๆ ระบุไว้คุณสามารถใช้วัตถุที่แฮชได้ (ไม่ใช่แค่สตริง) เป็นคีย์ dict ตัวอย่างเช่น,
>>> d = {(2, 3): True,}
>>> assert d[(2, 3)] is True
>>>
ถูกกฎหมาย แต่
>>> 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
>>>
ไม่ใช่. สิ่งนี้ช่วยให้คุณสามารถเข้าถึงตัวอักษรที่พิมพ์ได้ทั้งหมดหรือวัตถุที่แฮชได้อื่น ๆ สำหรับปุ่มพจนานุกรมของคุณซึ่งคุณไม่มีเมื่อเข้าถึงแอตทริบิวต์ของวัตถุ นี้จะทำให้มายากลดังกล่าวเป็นไปได้เป็นวัตถุ metaclass แคชเช่นสูตรจากที่งูหลามตำรา (Ch. 9)
ประเด็นที่ฉันแก้ไข
ฉันชอบความสวยงามของspam.eggs
กว่าspam['eggs']
(ผมคิดว่ามันดูสะอาด) namedtuple
และผมเริ่มอยากทำงานนี้เมื่อฉันได้พบกับ แต่ความสะดวกสบายของความสามารถในการทำดังต่อไปนี้สำคัญกว่า
>>> 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}
>>>
นี่เป็นตัวอย่างง่ายๆ แต่บ่อยครั้งที่ฉันพบว่าตัวเองใช้ dicts ในสถานการณ์ที่แตกต่างจากที่ฉันใช้obj.key
สัญกรณ์ (เช่นเมื่อฉันต้องอ่าน prefs จากไฟล์ XML) ในกรณีอื่น ๆ ที่ฉันอยากจะยกระดับคลาสแบบไดนามิกและตบคุณลักษณะบางอย่างเพื่อเหตุผลด้านสุนทรียภาพฉันยังคงใช้คำสั่งเพื่อความสอดคล้องเพื่อเพิ่มความสามารถในการอ่าน
ฉันแน่ใจว่า OP ได้รับการแก้ไขมาเป็นเวลานานเพื่อความพึงพอใจของเขา แต่ถ้าเขายังต้องการฟังก์ชั่นนี้ฉันแนะนำให้เขาดาวน์โหลดหนึ่งในแพ็คเกจจาก pypi ที่มี
พวงเป็นสิ่งที่ฉันคุ้นเคยมากกว่า ซับคลาสของdict
ดังนั้นคุณจึงมีฟังก์ชันทั้งหมดนั้น
AttrDictยังดูเหมือนว่ามันยังสวยดี แต่ฉันไม่เป็นที่คุ้นเคยกับมันและไม่ได้มองผ่านแหล่งที่มาเป็นรายละเอียดมากที่สุดเท่าที่ฉันมีพวง
- ติดยาเสพติดมีการบำรุงรักษาอย่างแข็งขันและให้การเข้าถึงเหมือน attr และอื่น ๆ
- ตามที่ระบุไว้ในการแสดงความคิดเห็นโดย Rotareti, พวงได้รับการคัดค้าน แต่มีการใช้งานที่เรียกว่าส้อมMunch
อย่างไรก็ตามเพื่อปรับปรุงความสามารถในการอ่านรหัสของฉันฉันขอแนะนำอย่างยิ่งให้เขาไม่ผสมผสานรูปแบบสัญกรณ์ของเขา หากเขาชอบสัญกรณ์นี้เขาควรจะยกตัวอย่างวัตถุไดนามิกให้เพิ่มคุณสมบัติที่ต้องการลงไปแล้วเรียกมันว่าวัน
>>> C = type('C', (object,), {})
>>> d = C()
>>> d.spam = 1
>>> d.eggs = 2
>>> d.ham = 3
>>> assert d.__dict__ == {'spam': 1, 'eggs': 2, 'ham': 3}
ในกรณีที่ฉันอัพเดตเพื่อตอบคำถามติดตามในความคิดเห็น
ในความคิดเห็น (ด้านล่าง) Elmoถาม:
ถ้าคุณต้องการที่จะลึกลงไปหนึ่งหรือไม่ (หมายถึงประเภท (... ))
ในขณะที่ฉันไม่เคยใช้กรณีการใช้งานนี้ (อีกครั้งฉันมักจะใช้ซ้อนกันdict
เพื่อความมั่นคง) รหัสต่อไปนี้ใช้งานได้:
>>> 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
มีประโยชน์มากสำหรับสิ่งนี้