กำหนดประเภทของวัตถุ Python
กำหนดประเภทของวัตถุด้วย type
>>> obj = object()
>>> type(obj)
<class 'object'>
แม้ว่าจะได้ผลก็ตามให้หลีกเลี่ยงแอตทริบิวต์ที่ขีดเส้นใต้สองเท่าเช่น__class__
- พวกเขาไม่ได้มีความหมายเชิงสาธารณะและแม้ว่าในกรณีนี้อาจจะไม่ได้ฟังก์ชั่นบิวด์อินมักจะมีพฤติกรรมที่ดีกว่า
>>> obj.__class__ # avoid this!
<class 'object'>
การตรวจสอบประเภท
มีวิธีง่ายๆในการพิจารณาว่าตัวแปรเป็นรายการพจนานุกรมหรืออย่างอื่นหรือไม่? ฉันได้รับวัตถุคืนซึ่งอาจเป็นประเภทใดประเภทหนึ่งและฉันต้องสามารถบอกความแตกต่างได้
นั่นเป็นคำถามที่แตกต่างอย่าใช้ประเภท - ใช้isinstance
:
def foo(obj):
"""given a string with items separated by spaces,
or a list or tuple,
do something sensible
"""
if isinstance(obj, str):
obj = str.split()
return _foo_handles_only_lists_or_tuples(obj)
กรณีนี้ครอบคลุมถึงกรณีที่ผู้ใช้ของคุณอาจทำสิ่งที่ฉลาดหรือสมเหตุสมผลโดยการทำคลาสย่อยstr
- ตามหลักการของการทดแทน Liskov คุณต้องการที่จะใช้อินสแตนซ์คลาสย่อยโดยไม่ทำลายโค้ดของคุณ - และisinstance
สนับสนุนสิ่งนี้
ใช้ Abstractions
ยิ่งไปกว่านั้นคุณอาจมองหา Abstract Base Class เฉพาะจากcollections
หรือnumbers
:
from collections import Iterable
from numbers import Number
def bar(obj):
"""does something sensible with an iterable of numbers,
or just one number
"""
if isinstance(obj, Number): # make it a 1-tuple
obj = (obj,)
if not isinstance(obj, Iterable):
raise TypeError('obj must be either a number or iterable of numbers')
return _bar_sensible_with_iterable(obj)
หรือเพียงแค่อย่าพิมพ์ตรวจสอบอย่างชัดเจน
หรือบางทีที่ดีที่สุดคือใช้การพิมพ์เป็ดและอย่าพิมพ์รหัสของคุณอย่างชัดเจน การพิมพ์เป็ดสนับสนุนการทดแทน Liskov ด้วยความสง่างามและการใช้คำฟุ่มเฟื่อยน้อยลง
def baz(obj):
"""given an obj, a dict (or anything with an .items method)
do something sensible with each key-value pair
"""
for key, value in obj.items():
_baz_something_sensible(key, value)
ข้อสรุป
- ใช้
type
เพื่อรับคลาสของอินสแตนซ์จริง
- ใช้
isinstance
เพื่อตรวจสอบคลาสย่อยจริงหรือ abstractions ที่ลงทะเบียนไว้อย่างชัดเจน
- และเพียงหลีกเลี่ยงการตรวจสอบประเภทที่เหมาะสม