Hãy nhớ rằng trong Python chúng tôi muốn sử dụng "gõ vịt". Vì vậy, bất cứ điều gì hoạt động như một danh sách có thể được coi là một danh sách. Vì vậy, đừng kiểm tra loại danh sách, hãy xem nó có hoạt động như một danh sách không.
Nhưng các chuỗi cũng hoạt động như một danh sách và thường đó không phải là điều chúng ta muốn. Có những lúc nó thậm chí là một vấn đề! Vì vậy, kiểm tra rõ ràng cho một chuỗi, nhưng sau đó sử dụng gõ vịt.
Đây là một chức năng tôi viết cho vui. Đây là phiên bản đặc biệt repr()
in bất kỳ chuỗi nào trong ngoặc vuông ('<', '>').
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
Đây là sạch sẽ và thanh lịch, tổng thể. Nhưng những gì isinstance()
kiểm tra làm ở đó? Đó là một loại hack. Nhưng nó là điều cần thiết.
Hàm này tự gọi đệ quy trên bất cứ thứ gì hoạt động như một danh sách. Nếu chúng ta không xử lý chuỗi đặc biệt, thì nó sẽ được coi như một danh sách và chia ra một ký tự một lần. Nhưng sau đó, cuộc gọi đệ quy sẽ cố gắng coi mỗi nhân vật là một danh sách - và nó sẽ hoạt động! Ngay cả một chuỗi ký tự cũng hoạt động như một danh sách! Hàm sẽ tiếp tục gọi chính nó một cách đệ quy cho đến khi stack stack.
Các hàm như thế này, phụ thuộc vào từng cuộc gọi đệ quy phá vỡ công việc cần thực hiện, phải thực hiện các chuỗi trường hợp đặc biệt - bởi vì bạn không thể phá vỡ một chuỗi dưới mức của chuỗi một ký tự và thậm chí là một chuỗi chuỗi -character hoạt động như một danh sách.
Lưu ý: try
/ except
là cách sạch nhất để thể hiện ý định của chúng tôi. Nhưng nếu mã này bằng cách nào đó rất quan trọng về thời gian, chúng tôi có thể muốn thay thế nó bằng một loại thử nghiệm nào đó để xem liệu đó arg
có phải là một chuỗi hay không. Thay vì kiểm tra loại, có lẽ chúng ta nên kiểm tra các hành vi. Nếu nó có một .strip()
phương thức, thì đó là một chuỗi, vì vậy đừng coi đó là một chuỗi; mặt khác, nếu nó có thể lập chỉ mục hoặc lặp lại, đó là một chuỗi:
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: Ban đầu tôi đã viết ở trên với một kiểm tra __getslice__()
nhưng tôi nhận thấy rằng trong collections
tài liệu mô-đun, phương pháp thú vị là __getitem__()
; Điều này có ý nghĩa, đó là cách bạn lập chỉ mục một đối tượng. Điều đó có vẻ cơ bản hơn __getslice__()
vì vậy tôi đã thay đổi ở trên.