Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/330.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/visual-studio-2012/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如果用Python键入duck,是否应该测试isinstance?_Python_Equality_Duck Typing - Fatal编程技术网

如果用Python键入duck,是否应该测试isinstance?

如果用Python键入duck,是否应该测试isinstance?,python,equality,duck-typing,Python,Equality,Duck Typing,您有一个Python类,它需要一个equals测试。Python应该使用duck类型,但是在eq函数中包含或排除isinstance测试(更好/更准确)吗?例如: class Trout(object): def __init__(self, value): self.value = value def __eq__(self, other): return isinstance(other, Trout) and self.value == o

您有一个Python类,它需要一个equals测试。Python应该使用duck类型,但是在eq函数中包含或排除isinstance测试(更好/更准确)吗?例如:

class Trout(object):
    def __init__(self, value):
        self.value = value

    def __eq__(self, other):
        return isinstance(other, Trout) and self.value == other.value

方法中使用isinstance非常常见。其原因是,如果
\uuuuuuuuuuuuuuuuuuuu
方法失败,它可以从另一个对象回退到
\uuuuuuuueq
方法。大多数普通的方法都是显式调用的,但是
\uuuuuuuuuuueq\uuuuuuu
是隐式调用的,所以需要三思而后行,才能更频繁地跳转

编辑(感谢提醒,Sven Marnach):

要使其回退,可以返回NotImplemented singleton,如下例所示:

class Trout(object):
    def __init__(self, value):
        self.value = value

    def __eq__(self, other):
        if isinstance(other, Trout):
            return self.value == other.value
        else:
            return NotImplemented
假设一条
彩虹鳟鱼
知道如何将自己与一条
鳟鱼
或另一条
彩虹鳟鱼
进行比较,但
鳟鱼
只知道如何将自己与一条
鳟鱼
进行比较。在本例中,如果您测试
mytrout==myrainbowtrout
,Python将首先调用
mytrout.\uuuueq\uuuuu(myrainbowtrout)
,请注意它失败了,然后调用
myrainbowtrout.\uueq\uuuuuuuuu(mytrout)
,成功了。

“duck-typing”原则是您不在乎其他
是什么,只要它具有
属性。因此,除非您的属性共享名称且语义冲突,否则我建议您这样做:

def __eq__(self, other):
    try:
        return self.value == other.value
    except AttributeError:
        return False # or whatever
(或者,您可以测试
other
是否具有
value
属性,但“请求原谅比获得许可更容易”)

使用
isintsance()。如果
isinstance()
检查失败,则不应立即返回
False
,但最好返回
NotImplemented
以提供
其他。
执行的机会:

def __eq__(self, other):
    if isinstance(other, Trout):
        return self.x == other.x
    return NotImplemented
这在多个类定义
\uuuu eq\uuu()
的类层次结构中尤为重要:


如果您像在原始代码中那样立即返回
False
,您将在
A(3)==B(3,4)
B(3,4)==A(3)

之间失去对称性。我认为这是
isinstance
的合法用例。这可能会导致一些非常愚蠢的事情,比如
鳟鱼(“彩虹”)==Lorikeet(“彩虹”)虽然几乎没有人会认为鱼和鸟一样。“令牌,那样的话,鸭子打字对你来说就不合适了。”顺便说一句,如果它们都在属性“value”中存储“rainbow”,那么结果将是相等的。。。。您可以根据OP的需要定义他们的
\uuuu eq\uuu
方法,只查看
字段。但是是的,这是鸭子打字的原则。不管你喜欢它还是离开它。这种方法的一个相当明显的缺点是try/except要慢得多(当我做测试时大约60%)。请看,try/except更像Pythonic,但我宁愿使用快速的非Pythonic代码,也不愿使用缓慢的Pythonic代码。:)Python异常的设计速度非常快,但它们当然不会像简单的类型查找那样快。但是,除非您将其用于数字处理,否则我更担心的是优化程序员的工作效率(阅读:扩展友好设计),而不是减少毫秒。虽然这个答案是正确的,但它并没有解释如何以一种实际上有助于回退到另一个对象的
\ueq()的方式实现
__()
class A(object):
    def __init__(self, x):
        self.x = x
    def __eq__(self, other):
        if isinstance(other, A):
            return self.x == other.x
        return NotImplemented
class B(A):
    def __init__(self, x, y):
        A.__init__(self, x)
        self.y = y
    def __eq__(self, other):
        if isinstance(other, B):
            return self.x, self.y == other.x, other.y
        return NotImplemented