Ingat bahwa dalam Python kami ingin menggunakan "bebek mengetik". Jadi, apa pun yang bertindak seperti daftar dapat diperlakukan sebagai daftar. Jadi, jangan periksa jenis daftar, lihat saja apakah itu bertindak seperti daftar.
Tetapi string juga berfungsi seperti daftar, dan sering kali bukan itu yang kita inginkan. Ada saat-saat ketika itu bahkan menjadi masalah! Jadi, periksa secara eksplisit untuk string, tetapi kemudian gunakan mengetik bebek.
Berikut adalah fungsi yang saya tulis untuk bersenang-senang. Ini adalah versi khusus repr()
yang mencetak urutan dalam kurung sudut ('<', '>').
def srepr(arg):
if isinstance(arg, basestring): # Python 3: isinstance(arg, str)
return repr(arg)
try:
return '<' + ", ".join(srepr(x) for x in arg) + '>'
except TypeError: # catch when for loop fails
return repr(arg) # not a sequence so just return repr
Ini bersih dan elegan, secara keseluruhan. Tapi apa yang isinstance()
dilakukan cek di sana? Itu semacam peretasan. Tetapi ini penting.
Fungsi ini menyebut dirinya secara rekursif pada apa pun yang bertindak seperti daftar. Jika kami tidak menangani string secara khusus, maka itu akan diperlakukan seperti daftar, dan membagi satu karakter sekaligus. Tetapi kemudian panggilan rekursif akan mencoba memperlakukan setiap karakter sebagai daftar - dan itu akan berhasil! Bahkan string satu karakter berfungsi sebagai daftar! Fungsi akan terus memanggil dirinya secara rekursif sampai stack overflow.
Fungsi seperti ini, yang bergantung pada setiap panggilan rekursif yang memecah pekerjaan yang harus dilakukan, harus memiliki string kasus khusus - karena Anda tidak dapat memecah string di bawah level string satu karakter, dan bahkan satu string -character bertindak seperti daftar.
Catatan: the try
/ except
adalah cara terbersih untuk mengekspresikan niat kami. Tetapi jika kode ini entah bagaimana kritis terhadap waktu, kita mungkin ingin menggantinya dengan semacam tes untuk melihat apakah arg
ada urutan. Daripada menguji jenisnya, kita mungkin harus menguji perilaku. Jika memiliki .strip()
metode, itu adalah string, jadi jangan menganggapnya sebagai urutan; jika tidak, jika itu dapat diindeks atau diubah, itu adalah urutan:
def is_sequence(arg):
return (not hasattr(arg, "strip") and
hasattr(arg, "__getitem__") or
hasattr(arg, "__iter__"))
def srepr(arg):
if is_sequence(arg):
return '<' + ", ".join(srepr(x) for x in arg) + '>'
return repr(arg)
EDIT: Saya awalnya menulis di atas dengan cek untuk __getslice__()
tetapi saya perhatikan bahwa dalam collections
dokumentasi modul, metode yang menarik adalah __getitem__()
; ini masuk akal, itulah cara Anda mengindeks objek. Tampaknya lebih mendasar daripada __getslice__()
itu saya mengubah di atas.