วัตถุประเภทใดที่อยู่ในโดเมนของ "subscriptable"
วัตถุประเภทใดที่อยู่ในโดเมนของ "subscriptable"
คำตอบ:
โดยทั่วไปหมายความว่าวัตถุใช้__getitem__()วิธีการ มันอธิบายถึงวัตถุที่เป็น "ภาชนะบรรจุ" ซึ่งหมายถึงวัตถุเหล่านั้นมีวัตถุอื่น ซึ่งรวมถึงสตริงรายการสิ่งอันดับและพจนานุกรม
[... ]ไวยากรณ์การจัดทำดัชนีที่เรียกว่าห้อยเพราะมันเทียบเท่ากับสัญกรณ์คณิตศาสตร์ที่ใช้ห้อยจริง เช่นa[1]เป็นงูหลามสำหรับสิ่งที่นักคณิตศาสตร์จะเขียนเป็นa₁ ดังนั้น "ห้อยได้" หมายถึง "สามารถห้อยได้" ซึ่งในแง่หลามหมายความว่ามีการดำเนินการ__getitem__()เนื่องจากเป็นเพียงน้ำตาลประโยคสำหรับa[1] a.__getitem__(1)
hasattrนั้นควรจะทำงานได้ดี แต่ไม่ใช่วิธี Pythonic ในการทำสิ่งต่าง ๆ ปฏิบัติหลามกระตุ้นให้เกิดการพิมพ์ดีดเป็ด หมายความว่าถ้าคุณวางแผนที่จะดึงรายการจากวัตถุของคุณโดยใช้ตัวห้อยไปข้างหน้าและทำมัน ถ้าคุณคิดว่ามันอาจจะไม่ทำงานเพราะวัตถุไม่ได้ subscriptable ห่อไว้ใน บล็อกที่มีtry except TypeError
จากด้านบนของหัวของฉันต่อไปนี้เป็นบิวด์อินเท่านั้นที่สามารถถอดได้:
string: "foobar"[3] == "b"
tuple: (1,2,3,4)[3] == 4
list: [1,2,3,4][3] == 4
dict: {"a":1, "b":2, "c":3}["c"] == 3
แต่คำตอบของ mipadiนั้นถูกต้อง - คลาสใด ๆ ที่ดำเนินการ__getitem__นั้นสามารถห้อยได้
วัตถุที่สามารถสคริปต์ได้เป็นวัตถุที่บันทึกการดำเนินการที่ทำไว้และสามารถจัดเก็บไว้เป็น "สคริปต์" ซึ่งสามารถเล่นซ้ำได้
ตัวอย่างเช่นดู: Application Scripting Framework
ทีนี้ถ้าอลิสแตร์ไม่รู้สิ่งที่เขาถามและหมายถึงวัตถุ "ที่สามารถอธิบายได้" (แก้ไขโดยผู้อื่น) ดังนั้นจากนั้น (ตามที่ mipadi ตอบด้วย) นี่คือสิ่งที่ถูกต้อง:
ออบเจกต์แบบห้อยได้คือวัตถุใด ๆ ที่ใช้__getitem__วิธีพิเศษ (คิดว่าเป็นรายการพจนานุกรม)
ความหมายของตัวห้อยในการคำนวณคือ: "สัญลักษณ์ (เขียนโดยความคิดในฐานะตัวห้อย แต่โดยปกติแล้วไม่ได้ใช้) ในโปรแกรมเพียงอย่างเดียวหรือกับคนอื่น ๆ เพื่อระบุองค์ประกอบหนึ่งของอาเรย์"
ตอนนี้ในตัวอย่างง่ายๆที่กำหนดโดย@ user2194711เราจะเห็นว่าองค์ประกอบต่อท้ายไม่สามารถเป็นส่วนหนึ่งของรายการเนื่องจากเหตุผลสองประการ: -
1) เราไม่ได้เรียกวิธีการต่อท้ายจริงๆ เพราะมันต้อง()เรียกมัน
2) ข้อผิดพลาดจะแสดงว่าฟังก์ชั่นหรือวิธีการไม่สามารถห้อยได้; หมายความว่าพวกเขาไม่สามารถจัดทำดัชนีเช่นรายการหรือลำดับ
ตอนนี้ดูสิ่งนี้: -
>>> var = "myString"
>>> def foo(): return 0
...
>>> var[3]
't'
>>> foo[3]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'function' object is not subscriptable
ซึ่งหมายความว่าไม่มีตัวห้อยหรือพูดว่าองค์ประกอบfunctionเหมือนเกิดขึ้นในลำดับ; []และเราไม่สามารถเข้าถึงได้เหมือนที่เราทำด้วยความช่วยเหลือของ
นอกจากนี้ยัง; ดังที่mipadiพูดในคำตอบของเขา; โดยทั่วไปหมายความว่าวัตถุใช้__getitem__()วิธีการ (ถ้ามันสามารถ subscriptable) ดังนั้นข้อผิดพลาดที่ผลิต:
arr.append["HI"]
TypeError: วัตถุ 'builtin_function_or_method' ไม่สามารถห้อยได้
ฉันมีปัญหาเดียวกันนี้ ฉันกำลังทำ
arr = []
arr.append["HI"]
ดังนั้นการใช้[ทำให้เกิดข้อผิดพลาด มันควรจะเป็นarr.append("HI")
ในฐานะที่เป็นข้อพิสูจน์ถึงคำตอบก่อนหน้านี้ที่นี่บ่อยครั้งมากนี่เป็นสัญญาณที่คุณคิดว่าคุณมีรายการ (หรือ dict หรือวัตถุอื่น ๆ ที่สามารถถอดได้) เมื่อคุณไม่ทำ
ตัวอย่างเช่นสมมติว่าคุณมีฟังก์ชันที่ควรส่งคืนรายการ
def gimme_things():
if something_happens():
return ['all', 'the', 'things']
ตอนนี้เมื่อคุณเรียกใช้ฟังก์ชันนั้นและsomething_happens()ด้วยเหตุผลบางอย่างไม่ส่งคืนTrueค่าจะเกิดอะไรขึ้น ความifล้มเหลวและคุณล้มเหลว gimme_thingsไม่ชัดเจนreturnอะไร - return Noneเป็นอย่างนั้นในความเป็นจริงมันจะโดยปริยาย จากนั้นรหัสนี้:
things = gimme_things()
print("My first thing is {0}".format(things[0]))
จะล้มเหลวด้วย " NoneTypeobject is subscriptable ไม่ได้" เพราะthingsก็คือNoneและคุณกำลังพยายามทำสิ่งNone[0]ที่ไม่สมเหตุสมผลเพราะ ... สิ่งที่ข้อความแสดงข้อผิดพลาดระบุ
มีสองวิธีในการแก้ไขข้อผิดพลาดนี้ในรหัสของคุณ - วิธีแรกคือการหลีกเลี่ยงข้อผิดพลาดโดยการตรวจสอบว่าใช้งานthingsได้จริงก่อนที่จะพยายามใช้
things = gimme_things()
if things:
print("My first thing is {0}".format(things[0]))
else:
print("No things") # or raise an error, or do nothing, or ...
หรือเทียบเท่ากับดักTypeErrorข้อยกเว้น;
things = gimme_things()
try:
print("My first thing is {0}".format(things[0]))
except TypeError:
print("No things") # or raise an error, or do nothing, or ...
อีกประการหนึ่งคือการออกแบบใหม่gimme_thingsเพื่อให้แน่ใจว่าจะส่งคืนรายการเสมอ ในกรณีนี้นั่นอาจจะเป็นการออกแบบที่เรียบง่ายกว่าเพราะมันหมายถึงถ้ามีหลายสถานที่ที่คุณมีจุดบกพร่องคล้ายกันพวกมันสามารถถูกเก็บไว้อย่างเรียบง่าย
def gimme_things():
if something_happens():
return ['all', 'the', 'things']
else: # make sure we always return a list, no matter what!
logging.info("Something didn't happen; return empty list")
return []
แน่นอนสิ่งที่คุณใส่ในelse:สาขาขึ้นอยู่กับกรณีการใช้งานของคุณ บางทีคุณควรเพิ่มข้อยกเว้นเมื่อsomething_happens()ล้มเหลวเพื่อทำให้ชัดเจนและชัดเจนยิ่งขึ้นว่ามีอะไรผิดพลาดจริงหรือไม่ การเพิ่มข้อยกเว้นในรหัสของคุณเองเป็นวิธีสำคัญที่จะทำให้คุณรู้ว่าเกิดอะไรขึ้นเมื่อมีบางอย่างล้มเหลว!
(โปรดสังเกตว่าการแก้ไขครั้งหลังนี้ยังไม่สามารถแก้ไขข้อผิดพลาดได้อย่างสมบูรณ์ - มันป้องกันคุณจากการพยายามห้อยNoneแต่things[0]ยังคงเป็นรายการที่ว่างIndexErrorเมื่อthingsคุณมีถ้าคุณมีวิธีที่tryคุณสามารถexcept (TypeError, IndexError)ดักมันได้)
hasattr(SomeClassWithoutGetItem, '__getitem__')เพื่อตรวจสอบว่าสิ่งใดที่สามารถถอดได้