Tôi nghĩ đây là một ví dụ hơi lừa đảo; có điều gì đó bạn chưa nói. Tôi đoán rằng khi bạn nói rằng bạn "có một giao diện", ý của bạn là bạn có một số mã chấp nhận một đối tượng và gọi phương thức run
của nó.
Nếu bạn không thử nghiệm loại đối tượng đó trước khi gọi phương thức run
, bạn đang sử dụng tính năng nhập vịt, đồng bằng và đơn giản! (Trong trường hợp này, nếu nó có phương thức run
thì đó là phương thức Runner
.) Miễn là bạn không sử dụng type
hoặc isinstance
trên đối tượng với phương thức run
thì bạn là Pythonic.
Câu hỏi về việc bạn có nên chấp nhận các chuỗi đơn giản hay chỉ các đối tượng nút là một câu hỏi khác biệt phụ. Các chuỗi và các đối tượng node
có thể không thực hiện cùng một giao diện! Chuỗi về cơ bản là không quack như một node
, vì vậy bạn không phải đối xử với chúng như một. Điều này giống như một con voi đi cùng, và nếu bạn muốn nó quack như một con vịt, bạn phải cung cấp cho voi một máy nghe nhạc băng và đào tạo con voi để sử dụng nó đầu tiên.
Vì vậy, đây không phải là vấn đề "nhập vịt" nữa mà là thiết kế giao diện. Bạn đang cố gắng quyết định mức độ nghiêm ngặt của giao diện của mình.
Để cung cấp cho bạn câu trả lời, sau đó, ở cấp độ này, tôi nghĩ rằng đó là phần lớn Pythonic giả định rằng run
trả về đối tượng node
. Không cần sử dụng isinstance
hoặc type
để kiểm tra điều đó. Chỉ cần giả vờ là đối tượng node
và nếu lập trình viên sử dụng giao diện của bạn bị sai và thấy ngoại lệ, thì họ sẽ phải đọc chuỗi tài liệu của bạn, điều này sẽ cho họ biết rằng run
phải vượt qua đối tượng node
.
Sau đó, nếu bạn muốn cũng chấp nhận chuỗi hoặc những thứ hoạt động như chuỗi, bạn có thể làm như vậy. Và vì chuỗi là loại nguyên thủy, tôi có thể nói không thích hợp khi sử dụng isinstance(obj, basestring)
(nhưng không phảitype(obj) == str
vì chuỗi đó loại bỏ chuỗi unicode, v.v.). Về cơ bản, đây là bạn đang rất tự do và tốt bụng với người dùng lười biếng của chương trình của bạn; bạn đã đi xa hơn và vượt ra ngoài bằng cách chấp nhận voi cũng như những thứ quack như vịt.
(Cụ thể hơn, tôi muốn nói đây là một chút như gọi iter
vào một cuộc tranh cãi vào lúc bắt đầu của một hàm mà bạn muốn chấp nhận cả hai máy phát điện và trình tự.)
Tôi hơi bối rối. Bạn đang nói về giá trị được truyền cho 'run' (thông qua' arg')? Hay bạn đang nói về cách xử lý giá trị giả định được trả về bởi phương thức 'run' của một đối tượng thực hiện giao diện' Runner'? – senderle
Tôi có nghĩa là sự trở lại. Tôi đã chỉnh sửa 'arg' để nó không bị phân tâm (cảm ơn vì đã chỉ ra điều này). – Owen