Python'da "ördek yazmayı" kullanmak istediğimizi unutmayın. Dolayısıyla liste gibi davranan her şey liste olarak kabul edilebilir. Bu nedenle, bir listenin türünü kontrol etmeyin, liste olarak davranıp davranmadığına bakın.
Ancak dizeler de bir liste gibi davranır ve genellikle istediğimiz bu değildir. Hatta bir sorun olduğu zamanlar var! Bu nedenle, açıkça bir dize olup olmadığını kontrol edin, ancak ördek yazmayı kullanın.
İşte eğlence için yazdığım bir fonksiyon. repr()
Köşeli parantez içindeki herhangi bir diziyi ('<', '>') basan özel bir sürümüdür .
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
Bu genel olarak temiz ve zarif. Ama bu isinstance()
çek orada ne yapıyor? Bu bir tür hack. Ancak bu çok önemlidir.
Bu işlev, liste gibi davranan her şeyi özyinelemeli olarak çağırır. Dizeyi özel olarak ele almazsak, bir liste gibi ele alınır ve her seferinde bir karakter bölünür. Ama sonra özyinelemeli çağrı her karaktere bir liste gibi davranmaya çalışır - ve işe yarar! Tek karakterli bir dize bile liste olarak çalışır! Yığın taşana kadar işlev özyinelemeli olarak çağrılmaya devam eder.
Yapılacak olan işi parçalayan her özyinelemeli çağrıya bağlı olan bu gibi işlevler, özel durum dizeleri gerektirir - çünkü tek karakterli bir dize ve hatta bir dizenin seviyesinin altındaki bir dizeyi parçalayamazsınız. -character string bir liste gibi davranır.
Not: try
/ except
, niyetlerimizi ifade etmenin en temiz yoludur. Ancak bu kod bir şekilde zaman açısından kritikse, arg
bir dizi olup olmadığını görmek için bir tür testle değiştirmek isteyebiliriz . Türü test etmek yerine, muhtemelen davranışları test etmeliyiz. Bir .strip()
yöntemi varsa, bir dizedir, bu yüzden bunu bir dizi olarak düşünmeyin; aksi takdirde, dizine eklenebilir veya yinelenebilirse, bu bir sekanstır:
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: Başlangıçta yukarıda bir çek ile yazdım __getslice__()
ama collections
modül belgelerinde ilginç yöntemin olduğunu fark ettim __getitem__()
; bu mantıklıdır, bir nesneyi bu şekilde endekslersiniz. __getslice__()
Yukarıdakileri değiştirdiğimden daha temel görünüyor .