我有一个不同块的2D数组,都是从Block继承而来的。我想检查我点击的块是否是污垢类型块,如下所示:
clickedblock = getClickedBlock()
if isinstance(clickedblock, Dirt):
place a block
else:
don't place a block
我听说isinstance
不好,应该避免,因为它会在代码中创建分叉。 isinstance
好几次使用?
我的问题的另一个更麻烦的解决方案是拥有一个名为“id'然后检查它是否等于某个常数,这意味着Dirt。但这听起来很糟糕,而且比简单的isinstance
更容易出错。
答案 0 :(得分:6)
您的示例似乎是isinstance()
的合法用例。
并不是isinstance()
不好,通常多态性可以用于相同的目的(这样可以使用更清晰的代码)。
但有时候,isinstance()
就是你所需要的。例如,检测变量是否为字符串的pythonic方法是isinstance(var, basestring)
。
答案 1 :(得分:1)
如果您不想使用它,您还有其他选择。传统的鸭子打字解决方案:
try:
clickedblock_place = clickedblock.place
except AttributeError:
# don't place block
else:
clickedblock_place()
或者您可以使用hasattr:
if hasattr(clickedblock, 'place'):
clickedblock.place()
我几乎没有使用isinstance除了检查(或者它是否已关闭?)继承层次结构,例如,如果你需要知道某个名称是否指向str或unicode:
if isinstance(str1, basestring):
blah, blah, blah
祝你好运,
麦克
答案 2 :(得分:0)
我想我会把它改成更像:
PLACEABLE_TYPES = [ Dirt ]
if isinstance(clickedblock, PLACEABLE_TYPES):
place the block
else:
don't place the block
但是评论中的想法:
if clickedblock.is_placeable(that_place):
place the block
else:
don't place the block
也有价值。
答案 3 :(得分:0)
我学会了使用它的艰难方法。问题在于结果对类定义的导入方式很敏感:
isinstance
测试的地方如果一个导入是相对的,而另一个是绝对的,则检查将失败。
从本质上讲,这就像检查SomeClass
与somepackage.SomeClass
之间的相等性。它们甚至来自同一文件,依此类推。另外,如果您以某种方式在somepackage
中同时拥有根目录和PYTHONPATH
目录,也会产生类似的结果-绝对样式的导入可以表示来自任何“源根”的路径,因此两种不同的绝对样式导入将导致实例检查失败。
人们可能会争论良好的实践将如何阻止这种情况的发生,但是良好的实践在很大程度上也就是没有把握机会。本着这种精神,我宁愿将某种抽象方法放在一个共同的祖先类中,以便以后可以依靠事物的庸俗性,而不是解释者认为它们是什么。
在Java中,每个类都解析为其完全限定的类名。这些在程序中是唯一的,实例测试很容易。在Python中,这些可能会很滑。