使用Python`isinstance`是对的吗?

问题描述 投票:6回答:4

我有一个不同块的2D数组,都继承自Block。我想检查我点击的块是否是污垢类型块,如下所示:

clickedblock = getClickedBlock()

if isinstance(clickedblock, Dirt):
    place a block

else:
    don't place a block

我听说isinstance很糟糕,应该避免,因为它会在代码中创建分叉。什么时候isinstance好用?

对我的问题另一个更麻烦的解决方案是使用一个名为'id'的Block字段,然后检查它是否等于某个常量,这意味着Dirt。但这听起来很糟糕,而且比简单的isinstance更容易出错。

python oop dynamic instance
4个回答
6
投票

您的示例似乎是isinstance()的合法用例。

并不是isinstance()是坏的,通常多态性可以用于相同的目的(这导致使用类的更清晰的代码)。

但有时候,isinstance()就是你所需要的。例如,检测变量是否为字符串的pythonic方法是isinstance(var, basestring)


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

祝你好运,迈克


1
投票

我学会了反对使用它的艰难方法。问题是结果对类定义的导入方式很敏感:

  • 在实例化对象的位置
  • 在进行isinstance测试的地方

如果一个导入是相对的而另一个是绝对的 - 检查将失败。基本上它就像检查SomeClasssomepackage.SomeClass之间的平等。它们来自同一个文件等等并不重要。此外,如果您以某种方式在somepackage中同时拥有根目录和PYTHONPATH目录,那么将会有类似的结果 - 然后绝对样式的导入可以表示来自任何一个“源根”的路径,因此会产生两个不同的绝对样式导入在失败的实例检查中。

有人可能会争论好的做法无论如何都会阻止这种情况的发生,但良好做法在很大程度上也是在不抓住机会。本着这种精神,我更喜欢将一些抽象方法放在一个共同的祖先类中,这样我以后可以依赖于庸医的方式而不是解释者认为它们是什么。

在Java中,每个类都解析为其完全限定的类名。这些在程序中是唯一的,实例测试是轻而易举的。在Python中,这些可能很滑。


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

也有价值。

© www.soinside.com 2019 - 2024. All rights reserved.