10

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

clickedblock = getClickedBlock()

if isinstance(clickedblock, Dirt):
    place a block

else:
    don't place a block

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

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

4

4 回答 4

11

您的示例似乎是isinstance().

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

但有时,isinstance()这正是您所需要的。例如,检测变量是否为字符串的 Python 方法是isinstance(var, basestring).

于 2012-11-29T22:55:42.070 回答
2

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

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

如果一个导入是相对的,另一个是绝对的 - 检查将失败。本质上,这就像检查SomeClassvs之间的相等性somepackage.SomeClass。它们来自同一个文件等等都没有关系。此外,如果您以某种方式同时拥有根目录和somepackage目录,则会出现类似的结果PYTHONPATH- 然后绝对样式导入可以表示来自任一“源根”的路径,因此两个不同的绝对样式导入将导致失败实例检查。

人们可能会争论良好的做法将如何阻止这种情况的发生,但良好的做法也主要是关于不冒险。本着这种精神,我更喜欢将一些抽象方法放在一个共同的祖先类中,这样我以后就可以依赖事物是如何嘎嘎作响的,而不是解释器认为它们是什么。

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

于 2019-03-28T08:54:14.180 回答
1

我想我会把它改成更像:

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

也有可取之处。

于 2012-11-29T23:00:59.770 回答
1

如果您不想使用它,您还有其他选择。传统的鸭子打字解决方案:

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

或者您可以使用hasattr

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

我几乎从不使用 isinstance 除了检查(或者它是否关闭?)继承层次结构,例如,如果您需要知道名称是否指向 a strOR a unicode

if isinstance(str1, basestring):
    blah, blah, blah
于 2012-11-29T23:31:02.373 回答