ฉันพยายามค้นหาอินเทอร์เน็ต แต่ไม่สามารถค้นหาความหมายของการแฮชได้
เมื่อพวกเขาพูดว่าวัตถุคืออะไรhashable
หรือhashable objects
มันหมายความว่าอย่างไร
ฉันพยายามค้นหาอินเทอร์เน็ต แต่ไม่สามารถค้นหาความหมายของการแฮชได้
เมื่อพวกเขาพูดว่าวัตถุคืออะไรhashable
หรือhashable objects
มันหมายความว่าอย่างไร
คำตอบ:
จากอภิธานศัพท์ Python :
วัตถุนั้น hashable ถ้ามันมีค่าแฮซึ่งไม่เคยเปลี่ยนแปลงในช่วงชีวิตของมัน (มันต้องการ
__hash__()
วิธีการ) และสามารถนำมาเปรียบเทียบกับวัตถุอื่น ๆ (มันต้องมีวิธีการ__eq__()
หรือ__cmp__()
) วัตถุที่แฮชที่เปรียบเทียบได้จะต้องมีค่าแฮชเหมือนกันHashability ทำให้วัตถุที่ใช้งานได้เป็นคีย์พจนานุกรมและสมาชิกชุดเนื่องจากโครงสร้างข้อมูลเหล่านี้ใช้ค่าแฮชภายใน
วัตถุในตัวที่ไม่เปลี่ยนรูปแบบของ Python ทั้งหมดนั้น hashable ในขณะที่ไม่มีคอนเทนเนอร์ที่ไม่แน่นอน (เช่นรายการหรือพจนานุกรม) วัตถุซึ่งเป็นอินสแตนซ์ของคลาสที่ผู้ใช้กำหนดจะแฮชตามค่าเริ่มต้น
id()
พวกเขาทั้งหมดเปรียบเทียบไม่เท่ากันและค่าแฮชของพวกเขาคือของพวกเขา
hash value
ตอนนี้มีค่าแฮช คุณสามารถยกตัวอย่าง
__hash__()
ค่าแฮชเป็นผลมาจากการเรียก โดยทั่วไปแล้วโปรดดูen.wikipedia.org/wiki/Hash_function
id(object)
เป็น 16x object.__hash__()
ผลมาจากการ ดังนั้นคำศัพท์ที่ตัดตอนมาไม่ถูกต้องสำหรับรุ่นนี้ - ค่าแฮชไม่ได้id()
แต่มาจากมัน (ตามที่ระบุไว้ในเอกสารที่ปรับปรุงแล้วสำหรับ python 2.7.12)
hash((1, [2, 3]))
จะเห็นมันในการดำเนินการ ฉันโพสต์คำขอเพื่อแก้ไขรายการคำศัพท์เพื่อแฮช
คำตอบทั้งหมดที่นี่มีคำอธิบายการทำงานที่ดีของวัตถุที่ลบได้ในหลาม แต่ฉันเชื่อว่าเราต้องเข้าใจคำว่า Hashing ก่อน
Hashingเป็นแนวคิดในวิทยาการคอมพิวเตอร์ที่ใช้ในการสร้างโครงสร้างข้อมูลการเข้าถึงแบบสุ่มหลอกที่มีข้อมูลจำนวนมากถูกจัดเก็บและเข้าถึงได้อย่างรวดเร็ว
ตัวอย่างเช่นถ้าคุณมี 10,000 เบอร์โทรศัพท์และคุณต้องการเก็บไว้ในอาเรย์ (ซึ่งเป็นโครงสร้างข้อมูลแบบลำดับที่เก็บข้อมูลในหน่วยความจำที่ต่อเนื่องกันและให้การเข้าถึงแบบสุ่ม) แต่คุณอาจไม่ได้มีจำนวนที่ต่อเนื่องกัน ตำแหน่งหน่วยความจำ
ดังนั้นคุณสามารถใช้อาร์เรย์ขนาด 100 แทนและใช้ฟังก์ชันแฮชเพื่อแมปชุดของค่ากับดัชนีเดียวกันและค่าเหล่านี้สามารถเก็บไว้ในรายการที่เชื่อมโยงได้ สิ่งนี้มีประสิทธิภาพคล้ายกับอาเรย์
ตอนนี้ฟังก์ชั่นแฮชสามารถทำได้ง่ายเพียงแค่หารจำนวนด้วยขนาดของอาเรย์และนำส่วนที่เหลือเป็นดัชนี
สำหรับรายละเอียดเพิ่มเติมโปรดดูที่https://en.wikipedia.org/wiki/Hash_function
นี่เป็นอีกหนึ่งแหล่งอ้างอิงที่ดี: http://interactivepython.org/runestone/static/pythonds/SortSearch/Hashing.html
สิ่งใดที่ไม่สามารถเปลี่ยนแปลงได้ (หมายถึงไม่แน่นอนอาจมีการเปลี่ยนแปลง) สามารถถูกแฮช นอกจากฟังก์ชั่นแฮชที่จะมองหาแล้วหากคลาสมีมันด้วยเช่น dir(tuple)
และมองหา__hash__
วิธีการนี่คือตัวอย่างบางส่วน
#x = hash(set([1,2])) #set unhashable
x = hash(frozenset([1,2])) #hashable
#x = hash(([1,2], [2,3])) #tuple of mutable objects, unhashable
x = hash((1,2,3)) #tuple of immutable objects, hashable
#x = hash()
#x = hash({1,2}) #list of mutable objects, unhashable
#x = hash([1,2,3]) #list of immutable objects, unhashable
รายการประเภทไม่เปลี่ยนรูป:
int, float, decimal, complex, bool, string, tuple, range, frozenset, bytes
รายการประเภทที่ไม่แน่นอน:
list, dict, set, bytearray, user-defined classes
Ellipsis
dict
hash(MyClass)
__hash__
__eq__
ยิ่งไปกว่านั้นคลาสที่ผู้ใช้กำหนดเองใช้เมธอดเหล่านี้ (และสามารถแฮชได้) เนื่องจากพวกมันสืบทอดเมธอดจากobject
(คลาสฐานสากล)
ในความเข้าใจของฉันตามอภิธานศัพท์ Python เมื่อคุณสร้างอินสแตนซ์ของวัตถุที่แฮชค่าที่ไม่สามารถเปลี่ยนแปลงได้จะถูกคำนวณตามสมาชิกหรือค่าของอินสแตนซ์ด้วย ตัวอย่างเช่นค่านั้นสามารถใช้เป็นคีย์ใน dict ดังต่อไปนี้:
>>> tuple_a = (1,2,3)
>>> tuple_a.__hash__()
2528502973977326415
>>> tuple_b = (2,3,4)
>>> tuple_b.__hash__()
3789705017596477050
>>> tuple_c = (1,2,3)
>>> tuple_c.__hash__()
2528502973977326415
>>> id(a) == id(c) # a and c same object?
False
>>> a.__hash__() == c.__hash__() # a and c same value?
True
>>> dict_a = {}
>>> dict_a[tuple_a] = 'hiahia'
>>> dict_a[tuple_c]
'hiahia'
เราสามารถพบว่าค่าแฮชของ tuple_a และ tuple_c เหมือนกันเนื่องจากมีสมาชิกเหมือนกัน เมื่อเราใช้ tuple_a เป็นกุญแจสำคัญใน dict_a เราจะพบว่าค่าสำหรับ dict_a [tuple_c] เหมือนกันซึ่งหมายความว่าเมื่อพวกเขาถูกใช้เป็นกุญแจสำคัญใน dict พวกเขากลับค่าเดียวกันเพราะค่าแฮช เหมือน. สำหรับวัตถุเหล่านั้นที่ไม่ได้แฮชวิธีแฮชจะถูกกำหนดเป็นไม่มี:
>>> type(dict.__hash__)
<class 'NoneType'>
ฉันเดาว่าค่าแฮชนี้คำนวณจากการเริ่มต้นอินสแตนซ์ไม่ใช่แบบไดนามิกนั่นเป็นเหตุผลว่าทำไมเฉพาะวัตถุที่ไม่เปลี่ยนรูปแบบเท่านั้นที่แฮช หวังว่านี่จะช่วยได้
ผมขอยกตัวอย่างการทำงานให้คุณเข้าใจวัตถุที่แฮชใน python ฉันรับ 2 Tuples สำหรับตัวอย่างนี้ค่าแต่ละค่าใน tuple มีค่าแฮชที่ไม่ซ้ำกันซึ่งไม่เคยเปลี่ยนแปลงระหว่างอายุการใช้งาน ดังนั้นตามนี้จึงมีค่าการเปรียบเทียบระหว่างสองสิ่งอันดับจะทำ เราสามารถรับค่าแฮชขององค์ประกอบ tuple โดยใช้ Id ()
ในไพ ธ อนมันหมายความว่าวัตถุสามารถเป็นสมาชิกของชุดเพื่อส่งกลับดัชนี นั่นคือพวกเขามีเอกลักษณ์ / รหัสเฉพาะ
ตัวอย่างเช่นใน python 3.3:
รายการโครงสร้างข้อมูลไม่สามารถแฮชได้ แต่โครงสร้างข้อมูลทูเปิลนั้นจะแฮชได้
id
ที่อยู่ (โดยประมาณ) ที่อยู่ของวัตถุในหน่วยความจำ
Hashable = ความสามารถในการถูกแฮช
โอเคอะไรที่คร่ำครวญ? ฟังก์ชั่นการแฮชคือฟังก์ชั่นที่รับวัตถุพูดสตริงเช่น“ Python” และส่งคืนรหัสขนาดคงที่ เพื่อความง่ายสมมติว่าค่าส่งคืนเป็นจำนวนเต็ม
เมื่อฉันเรียกใช้แฮช ('Python') ใน Python 3 ฉันจะได้รับ 5952713340227947791 เป็นผลลัพธ์ งูหลามรุ่นต่าง ๆ มีอิสระในการเปลี่ยนฟังก์ชันแฮชพื้นฐานดังนั้นคุณน่าจะได้รับค่าที่แตกต่างกัน สิ่งสำคัญคือไม่ว่าตอนนี้หลายครั้งที่ฉันเรียกแฮ ('Python') ฉันจะได้ผลลัพธ์เดียวกันกับ Python รุ่นเดียวกันเสมอ
แต่แฮช ('Java') จะคืนค่า 1753925553814008565 ดังนั้นหากวัตถุที่ฉัน hashing มีการเปลี่ยนแปลงผลลัพธ์ก็จะได้เช่นกัน ในทางกลับกันหากวัตถุที่ฉัน hashing ไม่เปลี่ยนแปลงแล้วผลลัพธ์ยังคงเหมือนเดิม
เหตุใดเรื่องนี้
ยกตัวอย่างเช่นพจนานุกรมภาษาไพ ธ อนจำเป็นต้องใช้กุญแจในการเปลี่ยนรูปแบบ นั่นคือกุญแจต้องเป็นวัตถุที่ไม่เปลี่ยนแปลง สตริงไม่เปลี่ยนแปลงใน Python เช่นเดียวกับชนิดพื้นฐานอื่น ๆ (int, float, bool) Tuples และ frozensets ก็ไม่เปลี่ยนรูป ในทางกลับกันรายการไม่เปลี่ยนแปลง (กล่าวคือพวกมันไม่แน่นอน) เพราะคุณสามารถเปลี่ยนแปลงได้ ในทำนองเดียวกัน dicts สามารถเปลี่ยนแปลงได้
ดังนั้นเมื่อเราพูดบางสิ่งที่แฮชเราหมายความว่ามันไม่เปลี่ยน หากฉันพยายามส่งประเภทที่ไม่แน่นอนไปยังฟังก์ชัน hash () มันจะล้มเหลว:
>>> hash('Python')
1687380313081734297
>>> hash('Java')
1753925553814008565
>>>
>>> hash([1, 2])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'
>>> hash({1, 2})
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'set'
>>> hash({1 : 2})
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'dict'
>>>
>>> hash(frozenset({1, 2}))
-1834016341293975159
>>> hash((1, 2))
3713081631934410656
ใน Python วัตถุใด ๆ ที่เปลี่ยนไม่ได้ (เช่นจำนวนเต็ม, บูลีน, สตริง, tuple) เป็น hashable ซึ่งหมายความว่าค่าของมันจะไม่เปลี่ยนแปลงในช่วงชีวิตของมัน วิธีนี้ช่วยให้ Python สร้างค่าแฮชที่ไม่ซ้ำกันเพื่อระบุค่าซึ่งพจนานุกรมสามารถใช้ในการติดตามคีย์ที่ไม่ซ้ำกันและตั้งค่าให้ติดตามค่าที่ไม่ซ้ำ
นี่คือเหตุผลที่ Python ต้องการให้เราใช้ประเภทข้อมูลที่ไม่เปลี่ยนรูปสำหรับคีย์ในพจนานุกรม
สำหรับการสร้างตาราง hashing ตั้งแต่เริ่มต้นค่าทั้งหมดจะต้องตั้งค่าเป็น "ไม่มี" และแก้ไขเมื่อมีความต้องการเกิดขึ้น วัตถุที่ลบได้หมายถึงประเภทข้อมูลที่แก้ไขได้ (พจนานุกรมรายการ ฯลฯ ) ไม่สามารถกำหนดค่าเริ่มต้นอีกครั้งเมื่อตั้งค่าไว้ดังนั้นชุดจึงไม่สามารถแฮชได้ ในขณะที่ตัวแปรของ set () - frozenset () - สามารถแฮชได้
__hash__()