เมื่อใดจึงจะใช้พจนานุกรม vs tuple ใน Python


31

ตัวอย่างที่เฉพาะเจาะจงในใจคือรายการชื่อไฟล์และขนาดของไฟล์ ฉันไม่สามารถตัดสินใจได้ว่ารายการในรายการแต่ละคนควรอยู่ในรูปแบบหรือเพียงแค่{"filename": "blabla", "size": 123} ("blabla", 123)พจนานุกรมดูเหมือนว่าฉันจะมีเหตุผลมากกว่าเพราะการเข้าถึงขนาดfile["size"]นั้นมีคำอธิบายมากกว่าfile[1]... แต่ฉันไม่รู้จริงๆ คิด?


ในฐานะที่เป็นภาคผนวกพิจารณาtuple เอาออกถ้าคุณกังวลเกี่ยวกับ readabilities ของ tuples - fname, file_size = fileซึ่งข้อมูลดังกล่าวข้างต้นเป็น tuple ของคุณจะทำไปด้วยและแทนที่ด้วยfile[1] file_sizeแน่นอนว่านี่เป็นเอกสารที่ดี
nlsdfnbch

2
มันขึ้นอยู่กับโครงสร้างข้อมูลที่คุณกำลังสร้างและคุณตั้งใจจะเข้าถึงมันอย่างไร (โดยชื่อไฟล์? โดยดัชนี? ทั้งคู่?) มันเป็นเพียงโครงสร้างตัวแปร / ข้อมูลที่ถูกทิ้งหรือคุณอาจจะเพิ่มไอเท็มอื่น (/ คุณลักษณะ) รวมถึงขนาด? โครงสร้างจำเป็นต้องจำคำสั่งซื้อหรือไม่ คุณต้องการเรียงลำดับรายการขนาดหรือเข้าถึงตามตำแหน่ง (เช่น "ไฟล์ที่ใหญ่ที่สุด / เล็กที่สุด") คำตอบที่ดีที่สุดอาจเป็น dict, OrderedDict, ชื่อ tuple, รายการเก่าแบบธรรมดาหรือคลาสที่กำหนดเองของคุณเอง ต้องการบริบทเพิ่มเติมจากคุณ
smci

คำตอบ:


78

ฉันจะใช้namedtuple:

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

ตอนนี้คุณสามารถใช้file.sizeและfile.filenameในโปรแกรมของคุณซึ่งเป็น IMHO รูปแบบที่อ่านได้มากที่สุด หมายเหตุnamedtupleสร้างวัตถุไม่เปลี่ยนรูปเช่น tuples และพวกเขามีน้ำหนักเบากว่าพจนานุกรมตามที่อธิบายไว้ที่นี่


1
ขอบคุณความคิดที่ดีไม่เคยได้ยินพวกเขามาก่อนวันนี้ (ฉันเป็นคนเจ้าเล่ห์ที่ Python) คำถาม: จะเกิดอะไรขึ้นถ้ามีคนอื่นในรหัสกำหนด "คลาส" เดียวกันซึ่งอาจแตกต่างกันเล็กน้อย เช่นในไฟล์ต้นฉบับอื่นผู้ร่วมงานของ Bob มีFilesize = namedtuple('Filesize', 'filepath kilobytes')
user949300

นอกจากนี้คุณยังสามารถใช้attrsโมดูลที่ดีมาก(สามารถค้นหาผ่านpipหรือเพียงแค่ค้นหามัน) ซึ่งช่วยให้คุณมีความสะดวกสบายเหมือนกันมากในการตั้งชื่อ tuple แต่สามารถให้ความไม่แน่นอนได้ ความแตกต่างของฟังก์ชั่นหลักคือattrs- คลาสที่ผลิตไม่ได้เปรียบเทียบเท่ากับ tuples ธรรมดาอย่างnamedtupleที่ทำ
mtraceur

3
@DocBrown Python ไม่มีแนวคิดของการประกาศ class, defและ=ทั้งหมดเพิ่งเขียนทับการใช้งานก่อนหน้านี้ repl.it
Challenger5

@ Challenger5: คุณถูกต้องความผิดพลาดของฉันดังนั้นคำตอบที่ถูกต้องคือ: นับคำจำกัดความล่าสุดไม่มีข้อผิดพลาดจาก Python runtime แต่ก็ยังมีพฤติกรรมที่คล้ายกันเช่นเดียวกับตัวแปรอื่น ๆ
Doc Brown

8
โปรดทราบว่าnamedtupleนี่เป็นประกาศสั้น ๆ สำหรับประเภทใหม่ที่มีแอตทริบิวต์ไม่เปลี่ยนรูป ซึ่งหมายความว่าคำตอบนั้นมีประสิทธิภาพ "ไม่ใช่tupleหรือไม่ใช่dictแต่เป็นobject" +1
jpmc26

18

{"filename": "blabla", "size": 123} หรือเพียงแค่ ("blabla", 123)

นี่เป็นคำถามอายุว่าจะเข้ารหัสรูปแบบ / สคีมาในวงดนตรีหรือนอกวง

คุณแลกเปลี่ยนหน่วยความจำบางส่วนเพื่อรับความสามารถในการอ่านและการพกพาที่มาจากการแสดงรูปแบบของข้อมูลที่ถูกต้องในข้อมูล หากคุณไม่ทำเช่นนี้ความรู้ที่ว่าฟิลด์แรกคือชื่อไฟล์และที่สองคือขนาดที่จะต้องเก็บไว้ที่อื่น ที่บันทึกหน่วยความจำ แต่ค่าใช้จ่ายในการอ่านและพกพา อะไรจะทำให้ บริษัท ของคุณเสียเงินมากขึ้น?

สำหรับประเด็นที่ไม่เปลี่ยนรูปจำไว้ว่าการเปลี่ยนรูปไม่ได้หมายความว่าไร้ประโยชน์เมื่อเผชิญกับการเปลี่ยนแปลง หมายความว่าเราต้องคว้าหน่วยความจำเพิ่มเติมทำการเปลี่ยนแปลงในสำเนาและใช้สำเนาใหม่ ไม่ฟรี แต่มักจะไม่ใช่ตัวแบ่งข้อตกลง เราใช้สตริงที่ไม่เปลี่ยนรูปสำหรับการเปลี่ยนแปลงสิ่งต่าง ๆ ตลอดเวลา

การพิจารณาก็คือการขยาย เมื่อคุณจัดเก็บข้อมูลเฉพาะตำแหน่งโดยไม่มีการเข้ารหัสข้อมูลรูปแบบคุณจะถูกลงโทษเพียงมรดกเดียวซึ่งไม่มีอะไรเลยนอกจากการเชื่อมโยงเขตข้อมูลเพิ่มเติมหลังจากเขตข้อมูลที่สร้างไว้แล้ว ฉันสามารถกำหนดฟิลด์ที่ 3 ให้เป็นวันที่สร้างและยังคงเข้ากันได้กับรูปแบบของคุณตั้งแต่ฉันกำหนดครั้งแรกและครั้งที่สองในลักษณะเดียวกัน

อย่างไรก็ตามสิ่งที่ฉันทำไม่ได้คือนำรูปแบบที่กำหนดโดยอิสระสองรูปแบบมารวมกันซึ่งมีเขตข้อมูลซ้อนทับกันบางรูปแบบไม่ได้เก็บไว้ในรูปแบบเดียวและมีประโยชน์กับสิ่งที่รู้เพียงรูปแบบเดียวหรือรูปแบบอื่น

เมื่อต้องการทำเช่นนั้นฉันจำเป็นต้องเข้ารหัสข้อมูลรูปแบบจากจุดเริ่มต้น ฉันต้องบอกว่า "ฟิลด์นี้คือชื่อไฟล์" การทำเช่นนั้นอนุญาตให้มีการสืบทอดหลายครั้ง

คุณอาจคุ้นเคยกับการสืบทอดเท่านั้นที่แสดงในบริบทของวัตถุ แต่แนวคิดเดียวกันนี้ใช้ได้กับรูปแบบข้อมูลเพราะวัตถุจะถูกจัดเก็บในรูปแบบข้อมูล มันเป็นปัญหาเดียวกัน

ดังนั้นใช้สิ่งที่คุณคิดว่าคุณต้องการได้มากที่สุด ฉันไปถึงความยืดหยุ่นเว้นแต่ฉันจะชี้ให้เห็นเหตุผลที่ดีไม่ได้


3
ตามจริงแล้วฉันสงสัยว่าใครก็ตามที่ไม่แน่ใจในการใช้รูปแบบในวงดนตรีหรือนอกวงดนตรีนั้นมีข้อกำหนดด้านประสิทธิภาพที่เข้มงวดซึ่งพวกเขาจำเป็นต้องใช้รูปแบบที่ไม่เหมาะสม
Alexander - Reinstate Monica

2
@Alexander จริงมาก ฉันชอบที่จะสอนคนเกี่ยวกับเรื่องนี้เพื่อให้พวกเขาเข้าใจสิ่งที่พวกเขากำลังมองหาเมื่อเผชิญหน้ากับการแก้ปัญหานอกวง รูปแบบไบนารีมักจะทำสิ่งนี้ด้วยเหตุผลที่ทำให้งงงวย ไม่ใช่ทุกคนที่ต้องการพกพา สำหรับเหตุผลด้านประสิทธิภาพหากเป็นเรื่องสำคัญให้พิจารณาการบีบอัดก่อนที่จะหันไปใช้นอกแบนด์
candied_orange

โปรดจำไว้ว่า OP กำลังใช้ Python ดังนั้นพวกเขาอาจไม่ได้กังวลเกี่ยวกับประสิทธิภาพมากเกินไป รหัสระดับสูงส่วนใหญ่ควรเขียนด้วยความสามารถในการอ่านก่อน การเพิ่มประสิทธิภาพก่อนวัยอันควรเป็นรากฐานของความชั่วร้ายทั้งหมด
Dagrooms

@Dagrooms ไม่ชอบ Python มันทำงานได้ดีในหลายกรณี แต่อย่างอื่นฉันเห็นด้วยกับทุกสิ่งที่คุณพูด จุดของฉันคือการพูดว่า "นี่คือเหตุผลที่คนทำอย่างนั้นนี่คือเหตุผลที่คุณอาจไม่สนใจ"
candied_orange

@CandiedOrange ฉันไม่ได้เกลียดภาษาฉันใช้มันในการทำงานประจำวันของฉัน ฉันไม่ชอบวิธีที่ผู้ใช้ใช้
Dagrooms

7

ฉันจะใช้คลาสที่มีคุณสมบัติสองอย่าง file.sizeเป็น nicer กว่าอย่างใดอย่างหนึ่งหรือfile[1]file["size"]

เรียบง่ายดีกว่าซับซ้อน


ในกรณีที่มีคนสงสัยว่า: สำหรับการสร้าง JSON ทั้งสองทำงานได้ดีเท่ากัน: file = Filesize(filename='stuff.txt', size=222)และfiletup = ("stuff.txt", 222)ทั้งคู่ก็สร้าง JSON เดียวกันjson.dumps(file)และjson.dumps(filetup)ส่งผลให้:'["stuff.txt", 222]'
Juha Untinen

5

ชื่อไฟล์มีความพิเศษหรือไม่? หากเป็นเช่นนั้นคุณสามารถคัดลอกรายการทั้งหมดและใช้พจนานุกรมบริสุทธิ์สำหรับไฟล์ทั้งหมด เช่น (เว็บไซต์สมมุติ)

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

ฯลฯ ...

ตอนนี้คุณไม่ได้รับ "ชื่อ" และ "ขนาด" คุณเพียงแค่ใช้รหัสและคุณค่า แต่บ่อยครั้งที่สิ่งนี้ดูเป็นธรรมชาติมากกว่า YMMV

หากคุณจริงๆต้องการ "ขนาด" เพื่อความชัดเจนหรือคุณต้องคุ้มค่ามากกว่าหนึ่งไฟล์แล้ว:

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

0

ในไพ ธ อนพจนานุกรมเป็นวัตถุที่ไม่แน่นอน อีกด้านหนึ่ง tuple เป็นวัตถุที่ไม่เปลี่ยนรูป

หากคุณต้องการเปลี่ยนคีย์พจนานุกรมคู่ค่ามักจะหรือทุกครั้ง ฉันแนะนำให้ใช้พจนานุกรม

หากคุณมีข้อมูลคงที่ / ฉันแนะนำให้ใช้ tuple

# 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'

แต่ไม่สามารถเปลี่ยนข้อมูลทูเปิลได้โดยใช้โอเปอเรเตอร์ที่ได้รับมอบหมาย

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.