【发布时间】:2011-04-28 22:32:07
【问题描述】:
我正在编写一个封装任意对象的类,包括简单类型。我想让“is”关键字对封装的值进行操作,比如这个行为:
Wrapper(True) is True -> True
Wrapper(False) is True -> False
Wrapper(None) is None -> True
Wrapper(1) is 1 -> True
有没有我可以重写的对象方法来获得这种行为?
【问题讨论】:
标签: python
我正在编写一个封装任意对象的类,包括简单类型。我想让“is”关键字对封装的值进行操作,比如这个行为:
Wrapper(True) is True -> True
Wrapper(False) is True -> False
Wrapper(None) is None -> True
Wrapper(1) is 1 -> True
有没有我可以重写的对象方法来获得这种行为?
【问题讨论】:
标签: python
没有。 is、and 和 or 不能重载。
【讨论】:
is 不能被覆盖。字典查找和集合查找使用is 进行快速相等检查,因为__eq__ 是可覆盖的并且可能非常慢。如果is 行为是可覆盖的,则无法保证快速的字典查找,这将不利于 python 的性能。
通常,如果您想根据值来测试相等性(如果 x 为 1、True 或 None),无论如何您都应该使用 == 运算符。如果你想使用is 操作符,你通常会测试某个东西是否引用了其他东西,比如list1 is list2。
如果要为== 定义特殊行为,可以在类定义中定义__eq__。
【讨论】:
x is 1 很危险,但x is None 完全没问题。 True、False 和 None 是 guaranteed to be singletons,我 认为 整数 -5 到 257 也在 CPython 中静态分配,但您可能能够创建这些整数之一这不是is 相同。
is 本身不能重载,但您可能对其他可能适合您的用例的"Reflection" magic methods 感兴趣(因为您正在查看此线程):
__instancecheck__(self, instance)检查实例是否是您定义的类的实例(例如isinstance(instance, class)。
__subclasscheck__(self, subclass)检查一个类是否是您定义的类的子类(例如issubclass(subclass, class))。
【讨论】:
没有。
is、and和or不能重载。
确实如此。我认为关键字是保留的,不能重载或更改。
见: http://docs.python.org/2/reference/lexical_analysis.html#keywords
"以下标识符作为保留字,或者语言的关键字,不能作为普通标识符使用。"
名单如下: ['and', 'as', 'assert', 'break', 'class', 'continue', 'def', 'del', 'elif', 'else', 'except', 'exec', ' finally'、'for'、'from'、'global'、'if'、'import'、'in'、'is'、'lambda'、'not'、'or'、'pass'、'print' , 'raise', 'return', 'try', 'while', 'with', 'yield']
这个列表可以通过命令查看
keyword.kwlist
(别忘了先导入关键字)
还有:
keyword.iskeyword('is')
返回真
更新:
我的回答很糟糕,我应该感到难过。
我自己搞砸了 del 。我不知道为什么我没有注意到...
第二次尝试:
以下文档提供了类上可自定义行为的完整列表。这包括用于覆盖和重载运算符的所有方法。不包括“是”。
http://docs.python.org/2/reference/datamodel.html#special-method-names
尽我所能。
【讨论】:
del可以重载,例如,你可以重载del x[i]或del x.attr。问题在于语义是否可以改变,而不是语法。
in 可以直接重载。 as 可以在上下文管理器中部分重载。 import 和 for 可以间接重载。