【问题标题】:How to override the `is` operator [duplicate]如何覆盖`is`运算符[重复]
【发布时间】:2010-11-12 01:26:58
【问题描述】:

可能重复:
python: class override “is” behavior

我正在尝试覆盖 is 运算符,以便我可以执行类似的操作

if tom is writer:
   print 'tom is writing'
elif tom is programmer:
   print 'tom is programming'

这在 python 中可行吗?

【问题讨论】:

  • 您的意思是“is”还是“isa”?这对我来说就像“isa”。
  • 假设您的示例中的“tom”是一个对象,您不能只使用像 tom.is_writer() 和 tom.is_programmer() 这样的方法吗?
  • @uzi 在我的例子中,writerprogrammer 是工作,它们太多了,无法在 tom 类中实现。目前我正在使用类似tom.works_as_a(writer)
  • 建议您将works_as_a() 替换为is_a()。不要覆盖语言基础的东西。

标签: python operators


【解决方案1】:

据我所知,您不能覆盖“is”,因为它通过比较两个对象的内存地址(即指针比较)来测试两个对象是否同一个对象。您可能希望通过实现 tom 的 __eq__ 方法来覆盖 '=='。

【讨论】:

    【解决方案2】:

    测试对象类型的 Python 方法是使用 isinstance,如isinstance(tom,Writer)

    但是,每当您开始编写读起来像您的示例的代码时,请考虑改用多态性。这是一个简单的类层次结构,可以满足您的要求,无需调用 isinstance:

    class Worker(object):
        def __init__(self, name):
            self.name = name
    
        def is_doing(self):
            return "working"
    
    class Writer(Worker):
        def is_doing(self):
            return "writing"
    
    class Programmer(Worker):
        def is_doing(self):
            return "programming"
    
    workers = [
        Writer("Tom"),
        Programmer("Dick"),
        ]
    
    for w in workers:
        print "%s is %s" % (w.name, w.is_doing())
    

    打印:

    Tom is writing
    Dick is programming
    

    现在您只需将新的子类添加到 Worker 并实现 is_doing,您就不必维护一些类型到活动值的表。

    这种多态模式是传统的 O-O,但在 Python 中,您甚至不限于 Worker 的子类 - 任何实现 is_doing 并具有 name 属性的对象都可以工作:

    class Fish(object):
        def __init__(self, n):
            self.name = n
        def is_doing(self):
            return "swimming"
    
    workers.append(Fish("Wanda"))
    
    for w in workers:
        print "%s is %s" % (w.name, w.is_doing())
    

    将打印:

    Tom is writing
    Dick is programming
    Wanda is swimming
    

    【讨论】:

    • 谢谢。但是多态性对我不起作用,因为我称之为job 的实体并不完全是工作。一个人可以同时拥有多个此类实体。