ฉันสงสัยว่าจะทำอย่างไรดีกว่า:
d = {'a': 1, 'b': 2}
'a' in d
True
หรือ:
d = {'a': 1, 'b': 2}
d.has_key('a')
True
ฉันสงสัยว่าจะทำอย่างไรดีกว่า:
d = {'a': 1, 'b': 2}
'a' in d
True
หรือ:
d = {'a': 1, 'b': 2}
d.has_key('a')
True
คำตอบ:
in แน่นอนยิ่งกว่า pythonic
ในความเป็นจริงhas_key()จะถูกลบออกในหลาม 3.x
keys()เป็นเพียงมุมมองแบบ set-like ลงในพจนานุกรมแทนที่จะเป็นสำเนาดังนั้นx in d.keys()O (1) ยังคงx in dเป็น Pythonic มากกว่า
                    x in d.keys()ต้องสร้างและทำลายวัตถุชั่วคราวพร้อมกับการจัดสรรหน่วยความจำที่เกี่ยวข้องซึ่งx in d.keys()เป็นเพียงการดำเนินการทางคณิตศาสตร์ (คำนวณแฮช) และทำการค้นหา โปรดทราบว่าd.keys()มีเพียงประมาณ 10 เท่าเท่านั้นซึ่งยังไม่นานจริง ๆ ฉันยังไม่ได้ตรวจสอบ แต่ฉันก็ยังค่อนข้างแน่ใจว่ามันเป็นเพียง O (1)
                    in ชนะมือลงไม่ใช่แค่ในความสง่างาม (และไม่ถูกคัดค้าน ;-) แต่รวมถึงประสิทธิภาพเช่น:
$ python -mtimeit -s'd=dict.fromkeys(range(99))' '12 in d'
10000000 loops, best of 3: 0.0983 usec per loop
$ python -mtimeit -s'd=dict.fromkeys(range(99))' 'd.has_key(12)'
1000000 loops, best of 3: 0.21 usec per loopในขณะที่การสังเกตต่อไปนี้ไม่เป็นความจริงเสมอไปคุณจะสังเกตได้ว่าโดยปกติแล้วใน Python โซลูชันที่เร็วกว่านั้นจะดูดีและ Pythonic นั่นเป็นเหตุผลว่าทำไมจึง-mtimeitมีประโยชน์ - ไม่ใช่แค่เกี่ยวกับการบันทึกหนึ่งร้อยนาโนวินาทีที่นี่และที่นั่น! -)
has_keyดูเหมือนจะเป็น O (1) ด้วย
                    อ้างอิงจากเอกสารหลาม:
has_key()key in dจะเลิกในความโปรดปรานของ
has_key()ถูกลบออกใน Python 3
                    ใช้dict.has_key()ถ้า (และเฉพาะในกรณี) รหัสของคุณจะต้องสามารถรันได้โดย Python เวอร์ชันที่เก่ากว่า 2.3 (เมื่อkey in dictถูกนำมาใช้)
มีตัวอย่างหนึ่งที่inฆ่าประสิทธิภาพได้จริง
ถ้าคุณใช้inในโอ (1) ภาชนะที่มีเพียงการดำเนินการ__getitem__และhas_key()แต่ไม่__contains__ว่าคุณจะเปิด O (1) ค้นหาเป็น O (N) ค้นหา (ตามที่inอยู่กลับไปยังการค้นหาเชิงเส้นผ่าน__getitem__)
เห็นได้ชัดว่าการแก้ไขเล็กน้อย:
def __contains__(self, x):
    return self.has_key(x)has_key()เป็นที่เฉพาะเจาะจงกับงูหลาม 2 พจนานุกรม in/ __contains__เป็น API ที่ถูกต้องที่จะใช้; สำหรับคอนเทนเนอร์ที่ไม่สามารถหลีกเลี่ยงการสแกนเต็มรูปแบบจะไม่มีhas_key()วิธีการใด ๆอยู่แล้วและหากมีวิธี O (1) วิธีนั้นจะใช้เฉพาะกรณีและขึ้นอยู่กับผู้พัฒนาที่จะเลือกประเภทข้อมูลที่เหมาะสมสำหรับปัญหา
                    has_keyเป็นวิธีพจนานุกรม แต่inจะทำงานกับคอลเลกชันใด ๆ และแม้__contains__จะหายไปinจะใช้วิธีอื่น ๆ เพื่อทำซ้ำคอลเลกชันเพื่อค้นหา
inทดสอบกับrangeวัตถุ ผมไม่แน่ใจว่าเกี่ยวกับประสิทธิภาพในการใช้ในหลาม 2 xrangeแม้ว่า ;)
                    __contains__สามารถคำนวณได้เล็กน้อยว่าค่าอยู่ในช่วงหรือไม่
                    rangeอินสแตนซ์ใหม่ทุกครั้ง การใช้อินสแตนซ์ที่มีอยู่ก่อนหน้าเดียวการทดสอบ "จำนวนเต็มในช่วง" จะเร็วขึ้นประมาณ 40% ในการกำหนดเวลาของฉัน
                    โซลูชัน dict.has_key () เลิกใช้แล้วใช้ 'ใน' - โปรแกรมแก้ไขข้อความประเสริฐ 3
ที่นี่ฉันได้นำตัวอย่างของพจนานุกรมชื่อ 'วัย' -
ages = {}
# Add a couple of names to the dictionary
ages['Sue'] = 23
ages['Peter'] = 19
ages['Andrew'] = 78
ages['Karren'] = 45
# use of 'in' in if condition instead of function_name.has_key(key-name).
if 'Sue' in ages:
    print "Sue is in the dictionary. She is", ages['Sue'], "years old"
else:
    print "Sue is not in the dictionary"ขยายการทดสอบประสิทธิภาพของ Alex Martelli ด้วยความคิดเห็นของ Adam Parkin ...
$ python3.5 -mtimeit -s'd=dict.fromkeys(range( 99))' 'd.has_key(12)'
Traceback (most recent call last):
  File "/usr/local/Cellar/python3/3.5.2_3/Frameworks/Python.framework/Versions/3.5/lib/python3.5/timeit.py", line 301, in main
    x = t.timeit(number)
  File "/usr/local/Cellar/python3/3.5.2_3/Frameworks/Python.framework/Versions/3.5/lib/python3.5/timeit.py", line 178, in timeit
    timing = self.inner(it, self.timer)
  File "<timeit-src>", line 6, in inner
    d.has_key(12)
AttributeError: 'dict' object has no attribute 'has_key'
$ python2.7 -mtimeit -s'd=dict.fromkeys(range(  99))' 'd.has_key(12)'
10000000 loops, best of 3: 0.0872 usec per loop
$ python2.7 -mtimeit -s'd=dict.fromkeys(range(1999))' 'd.has_key(12)'
10000000 loops, best of 3: 0.0858 usec per loop
$ python3.5 -mtimeit -s'd=dict.fromkeys(range(  99))' '12 in d'
10000000 loops, best of 3: 0.031 usec per loop
$ python3.5 -mtimeit -s'd=dict.fromkeys(range(1999))' '12 in d'
10000000 loops, best of 3: 0.033 usec per loop
$ python3.5 -mtimeit -s'd=dict.fromkeys(range(  99))' '12 in d.keys()'
10000000 loops, best of 3: 0.115 usec per loop
$ python3.5 -mtimeit -s'd=dict.fromkeys(range(1999))' '12 in d.keys()'
10000000 loops, best of 3: 0.117 usec per loopหากคุณมีสิ่งนี้:
t.has_key(ew)เปลี่ยนเป็นด้านล่างเพื่อใช้งานบน Python 3.X ขึ้นไป:
key = ew
if key not in tt.has_key(ew)ส่งคืนTrueถ้าการewอ้างอิงค่าเป็นกุญแจสำคัญในพจนานุกรมด้วย key not in tส่งคืนTrueถ้าค่าไม่ได้อยู่ในพจนานุกรม นอกจากนี้key = ewนามแฝงนั้นซ้ำซ้อนมาก if ew in tการสะกดคำที่ถูกต้องคือ ซึ่งเป็นสิ่งที่คำตอบที่ยอมรับจาก 8 ปีก่อนบอกคุณแล้ว