使用Python`isinstance`是对的吗?

时间:2012-11-29 22:45:20

标签: python oop dynamic instance

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

clickedblock = getClickedBlock()

if isinstance(clickedblock, Dirt):
    place a block

else:
    don't place a block

我听说isinstance不好,应该避免,因为它会在代码中创建分叉。 isinstance好几次使用?

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

4 个答案:

答案 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测试的地方

如果一个导入是相对的,而另一个是绝对的,则检查将失败。 从本质上讲,这就像检查SomeClasssomepackage.SomeClass之间的相等性。它们甚至来自同一文件,依此类推。另外,如果您以某种方式在somepackage中同时拥有根目录和PYTHONPATH目录,也会产生类似的结果-绝对样式的导入可以表示来自任何“源根”的路径,因此两种不同的绝对样式导入将导致实例检查失败。

人们可能会争论良好的实践将如何阻止这种情况的发生,但是良好的实践在很大程度上也就是没有把握机会。本着这种精神,我宁愿将某种抽象方法放在一个共同的祖先类中,以便以后可以依靠事物的庸俗性,而不是解释者认为它们是什么。

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