2012-11-29 10 views
6

Tôi có một mảng 2D gồm các khối khác nhau, tất cả đều được kế thừa từ Chặn. Tôi muốn kiểm tra xem khối mà tôi nhấp vào là một khối loại Dirt, như thế này:Sử dụng Python `isinstance` có đúng không?

clickedblock = getClickedBlock() 

if isinstance(clickedblock, Dirt): 
    place a block 

else: 
    don't place a block 

Tôi đã nghe nói rằng isinstance là xấu, và nên tránh vì nó tạo ra dĩa trong mã. Những gì thời gian sẽ isinstance là tốt để sử dụng?

Một giải pháp rườm rà khác cho vấn đề của tôi là có một trường Block gọi là 'id' và sau đó kiểm tra xem nó có bằng một số hằng số có nghĩa là Dirt hay không. Nhưng điều đó nghe có vẻ khá tệ và dễ bị sai lầm hơn là đơn giản isinstance.

+0

@DietrichEpp Nói chung? : p Tôi không đồng ý. – keyser

+0

@DietrichEpp Đó là lý do tại sao tôi hỏi ở đây để xác nhận. –

+0

@Keyser: Đó chính xác là quan điểm của tôi. Bạn không đồng ý, nhưng bạn không cho tôi biết tại sao bạn không đồng ý, vì vậy bạn không cho người khác cơ hội tạo nên tâm trí của chính họ nếu họ chọn. –

Trả lời

7

Ví dụ của bạn có vẻ giống như trường hợp sử dụng hợp pháp của isinstance().

Nó không phải là isinstance() là xấu, thường đa hình có thể được sử dụng cho cùng một mục đích (mà kết quả trong mã sạch hơn trong nơi lớp được sử dụng).

Nhưng đôi khi, isinstance() là những gì bạn cần. Ví dụ, cách pythonic phát hiện xem một biến là chuỗi hay không là isinstance(var, basestring).

1

tôi nghĩ rằng tôi muốn thay đổi nó trở nên giống như hơn:

PLACEABLE_TYPES = [ Dirt ] 
if isinstance(clickedblock, PLACEABLE_TYPES): 
    place the block 
else: 
    don't place the block 

nhưng ý tưởng trong các ý kiến ​​của:

if clickedblock.is_placeable(that_place): 
    place the block 
else: 
    don't place the block 

cũng có công đức.

+1

Ví dụ đầu tiên gần như chắc chắn là không chính xác! Nó sẽ thất bại nếu 'clickblock' là một phân lớp của' Dirt'. Tốt hơn là: 'if isinstance (clickblock, PLACEABLE_TYPES)'. Nhưng ví dụ thứ hai, 'clickblock.is_placeable (…)', có khả năng tốt hơn nhiều. –

1

Nếu bạn không muốn sử dụng, bạn có các tùy chọn khác. Truyền thống giải pháp vịt gõ:

try: 
    clickedblock_place = clickedblock.place 
except AttributeError: 
    # don't place block 
else: 
    clickedblock_place() 

Hoặc bạn có thể sử dụng hasattr:

if hasattr(clickedblock, 'place'): 
    clickedblock.place() 

Tôi hầu như không bao giờ sử dụng isinstance trừ kiểm tra lên (? Hoặc là nó xuống) hệ thống phân cấp thừa kế, chẳng hạn, ví dụ, nếu bạn cần phải biết nếu một tên trỏ đến một str HOẶC unicode:

if isinstance(str1, basestring): 
    blah, blah, blah 

may mắn, Mike

+3

* Vui lòng không sử dụng 'ngoại trừ:' *! Thật khủng khiếp, kinh khủng, và nó có thể sẽ cho con bạn một số desease không thể chữa được. Sử dụng 'except:' sẽ bắt * tất cả * ngoại lệ, điều này sẽ làm cho việc gỡ rối các lỗi hợp lệ trong '.place()' một cơn ác mộng, bắt ctrl-c và một loạt các thứ không mong muốn khác. –

+1

Nếu bạn muốn sử dụng 'try/except' (không * nhất thiết * xấu), hãy sử dụng:' try: place_block = clickedblock.place; ngoại trừ AttributeError: dont_place(); else: place_block() '- theo cách đó bạn sẽ thấy các lỗi hợp lệ trong phương thức' .place() '. –

+1

Cảm ơn bạn đã chỉnh sửa @David Wolever. Bạn tất nhiên là chính xác. Tôi đã vội vàng. – MikeHunter