วัตถุประเภทใดที่อยู่ในโดเมนของ "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]))
จะล้มเหลวด้วย " NoneType
object 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__')
เพื่อตรวจสอบว่าสิ่งใดที่สามารถถอดได้