Python 2 和 Python 3 中的内置类型的子类化
当子类化内置类型时,我注意到Python 2和Python 3之间在内置类型方法的返回类型上有一个相当重要的区别。以下代码说明了集合的这一点:
class MySet(set):
pass
s1 = MySet([1, 2, 3, 4, 5])
s2 = MySet([1, 2, 3, 6, 7])
print(type(s1.union(s2)))
print(type(s1.intersection(s2)))
print(type(s1.difference(s2)))
在 Python 2 中,所有返回值都是 MySet
类型。对于 Python 3,返回类型为 set
。我找不到任何关于结果应该是什么的文档,也找不到任何关于 Python 3 中的更改的文档。
无论如何,我真正关心的是:Python 3 中是否有一种简单的方法来获得 Python 中看到的行为2、无需重新定义内置类型的每一个方法?
When subclassing builtin types, I noticed a rather important difference between Python 2 and Python 3 in the return type of the methods of the built-in types. The following code illustrates this for sets:
class MySet(set):
pass
s1 = MySet([1, 2, 3, 4, 5])
s2 = MySet([1, 2, 3, 6, 7])
print(type(s1.union(s2)))
print(type(s1.intersection(s2)))
print(type(s1.difference(s2)))
With Python 2, all the return values are of type MySet
. With Python 3, the return types are set
. I could not find any documentation on what the result is supposed to be, nor any documentation about the change in Python 3.
Anyway, what I really care about is this: is there a simple way in Python 3 to get the behavior seen in Python 2, without redefining every single method of the built-in types?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
从 Python 2.x 迁移到 3.x 时,这并不是内置类型的一般变化 - 例如,
list
和int
具有相同的行为在 2.x 和 3.x 中。仅更改了集合类型以使其与其他类型保持一致,如此错误跟踪器问题中所述。恐怕没有真正好的方法让它按照旧的方式运行。这是我能够想出的一些代码:
这将简单地用返回您自己的类型的版本覆盖所有方法。 (有很多方法!)
也许对于您的应用程序,您可以不用覆盖
copy()
并坚持使用就地方法。This isn't a general change for built-in types when moving from Python 2.x to 3.x --
list
andint
, for example, have the same behaviour in 2.x and 3.x. Only the set type was changed to bring it in line with the other types, as discussed in this bug tracker issue.I'm afraid there is no really nice way to make it behave the old way. Here is some code I was able to come up with:
This will simply overwrite all methods with versions that return your own type. (There is a whole lot of methods!)
Maybe for your application, you can get away with overwriting
copy()
and stick to the in-place methods.也许一个元类为你完成所有这些单调的包装会让它变得更容易:
Perhaps a metaclass to do all that humdrum wrapping for you would make it easier:
作为 Sven 答案的后续,这里有一个通用包装解决方案,可以处理所有非特殊方法。这个想法是捕获来自方法调用的第一次查找,并安装一个执行类型转换的包装方法。在后续查找时,直接返回包装器。
注意事项:
1)这比我在代码中所希望的更加神奇。
2)我仍然需要手动包装特殊方法(
__and__
等),因为它们的查找绕过__getattribute__
As a follow-up to Sven's answer, here is a universal wrapping solution that takes care of all non-special methods. The idea is to catch the first lookup coming from a method call, and install a wrapper method that does the type conversion. At subsequent lookups, the wrapper is returned directly.
Caveats:
1) This is more magic trickery than I like to have in my code.
2) I'd still need to wrap special methods (
__and__
etc.) manually because their lookup bypasses__getattribute__