python 中的泛型/模板?
python 如何处理泛型/模板类型场景?假设我想创建一个外部文件“BinaryTree.py”并让它处理二叉树,但适用于任何数据类型。
所以我可以将自定义对象的类型传递给它,并拥有该对象的二叉树。这是如何在 python 中完成的?
How does python handle generic/template type scenarios? Say I want to create an external file "BinaryTree.py" and have it handle binary trees, but for any data type.
So I could pass it the type of a custom object and have a binary tree of that object. How is this done in python?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(10)
其他答案完全没问题:
但是,如果您仍然想要类型化变体,自 Python 3.5 以来有一个内置解决方案。
Python 文档中提供了可用类型注释的完整列表。
泛型类:
泛型函数:
静态类型检查:
您必须使用静态类型检查器,例如mypy 或 Pyre(由Meta/FB)来分析您的源代码。
安装mypy:
分析你的源代码,例如某个文件:
或目录:
mypy将检测并打印类型错误。上面提供的 Stack 示例的具体输出:
参考:有关 泛型 和运行 mypy
The other answers are totally fine:
However, if you still want a typed variant, there is a built-in solution since Python 3.5.
A full list of available type annotations is available in the Python documentation.
Generic classes:
Generic functions:
Static type checking:
You must use a static type checker such as mypy or Pyre (developed by Meta/FB) to analyze your source code.
Install mypy:
Analyze your source code, for example a certain file:
or directory:
mypy will detect and print type errors. A concrete output for the Stack example provided above:
References: mypy documentation about generics and running mypy
Python 使用鸭子类型,因此不需要特殊的语法来处理多种类型。
如果您有 C++ 背景,您会记得,只要模板函数/类中使用的操作是在某种类型
T
上定义的(在语法级别),您就可以使用在模板中输入T
。因此,基本上,它的工作方式是相同的:
但是您会注意到,除非您编写显式类型检查(通常不鼓励这样做),否则您将无法强制执行二叉树仅包含所选类型的元素。
Python uses duck typing, so it doesn't need special syntax to handle multiple types.
If you're from a C++ background, you'll remember that, as long as the operations used in the template function/class are defined on some type
T
(at the syntax level), you can use that typeT
in the template.So, basically, it works the same way:
You'll note however, that unless you write explicit type checking (which is usually discouraged), you won't be able to enforce that a binary tree contains only elements of the chosen type.
实际上现在你可以在 Python 3.5+ 中使用泛型。
请参阅 PEP-484 和 打字模块文档。
根据我的实践,它不是很无缝和清晰,特别是对于那些熟悉 Java 泛型的人来说,但仍然可用。
Actually now you can use generics in Python 3.5+.
See PEP-484 and typing module documentation.
According to my practice it is not very seamless and clear especially for those who are familiar with Java Generics, but still usable.
在提出了一些关于在 python 中创建泛型类型的好想法之后,我开始寻找其他有相同想法的人,但我找不到任何人。所以,就在这里。我尝试了一下,效果很好。它允许我们在 python 中参数化我们的类型。
您现在可以从此泛型类型派生类型。
这个解决方案很简单,并且确实有其局限性。每次创建泛型类型时,都会创建一个新类型。因此,继承
List( str )
作为父级的多个类将从两个单独的类继承。为了克服这个问题,您需要创建一个字典来存储内部类的各种形式并返回之前创建的内部类,而不是创建一个新的内部类。这将防止创建具有相同参数的重复类型。如果有兴趣,可以使用装饰器和/或元类制定更优雅的解决方案。After coming up with some good thoughts on making generic types in python, I started looking for others who had the same idea, but I couldn't find any. So, here it is. I tried this out and it works well. It allows us to parameterize our types in python.
You can now derive types from this generic type.
This solution is simplistic, and it does have it's limitations. Each time you create a generic type, it will create a new type. Thus, multiple classes inheriting
List( str )
as a parent would be inheriting from two separate classes. To overcome this, you need to create a dict to store the various forms of the inner class and return the previous created inner class, rather than creating a new one. This would prevent duplicate types with the same parameters from being created. If interested, a more elegant solution can be made with decorators and/or metaclasses.从 Python 3.12 开始,现在可以使用泛型类型和类型别名! (今天发布!)
遵循 PEP-695,现在可以编写如下代码:
也可以键入别名现在工作!即使使用泛型!
最后一个示例取自官方指南:
It is now possible to use generic types and type aliases starting from Python 3.12! (released today!)
Following PEP-695, one can now write code like:
Type aliasses also work now! Even using generics!
Last example taken from the official guidelines:
这是这个答案的一个变体,它使用元类来避免混乱的语法,并使用
打字
-styleList[int]
语法:使用这个新的元类,我们可以将我链接到的答案中的示例重写为:
这种方法有一些很好的好处
Here's a variant of this answer that uses metaclasses to avoid the messy syntax, and use the
typing
-styleList[int]
syntax:With this new metaclass, we can rewrite the example in the answer I link to as:
This approach has some nice benefits
由于 python 是动态类型的,所以这非常简单。事实上,您必须为 BinaryTree 类做额外的工作,才能不使用任何数据类型。
例如,如果您希望通过
key()
之类的方法将用于将对象放置在树中的键值在对象内可用,您只需调用key()
在物体上。例如:请注意,您永远不需要定义 object_to_insert 是什么类型的类。只要它有
key()
方法,它就可以工作。例外情况是,如果您希望它能够处理字符串或整数等基本数据类型。您必须将它们包装在一个类中才能使它们与您的通用二叉树一起使用。如果这听起来太重了,并且您想要实际上仅存储字符串的额外效率,那么抱歉,这不是 Python 所擅长的。
Since python is dynamically typed, this is super easy. In fact, you'd have to do extra work for your BinaryTree class not to work with any data type.
For example, if you want the key values which are used to place the object in the tree available within the object from a method like
key()
you just callkey()
on the objects. For example:Note that you never need to define what kind of class object_to_insert is. So long as it has a
key()
method, it will work.The exception is if you want it to work with basic data types like strings or integers. You'll have to wrap them in a class to get them to work with your generic BinaryTree. If that sounds too heavy weight and you want the extra efficiency of actually just storing strings, sorry, that's not what Python is good at.
看看内置容器是如何做到的。
dict
和list
等包含您喜欢的任何类型的异构元素。例如,如果您为树定义一个insert(val)
函数,它会在某个时候执行类似node.value = val
的操作,并且 Python 将处理休息。Look at how the built-in containers do it.
dict
andlist
and so on contain heterogeneous elements of whatever types you like. If you define, say, aninsert(val)
function for your tree, it will at some point do something likenode.value = val
and Python will take care of the rest.如果你使用Python 2或者想重写java代码。他们并不是真正的解决方案。这是我一晚上的工作内容: https://github.com/FlorianSteenbuck/python-generics< /a> 我仍然没有编译器,所以你目前使用它是这样的:
TODOs
>
)super
支持?
支持If you using Python 2 or want to rewrite java code. Their is not real solution for this. Here is what I get working in a night: https://github.com/FlorianSteenbuck/python-generics I still get no compiler so you currently using it like that:
TODOs
<? extends List<Number>>
)super
support?
support幸运的是,Python 中的通用编程已经做出了一些努力。
有一个库: generic
这是它的文档:http://generic.readthedocs.org/en/latest/
多年来没有任何进展,但您可以大致了解如何使用 &创建你自己的图书馆。
干杯
Fortunately there has been some efforts for the generic programming in python .
There is a library : generic
Here is the documentation for it: http://generic.readthedocs.org/en/latest/
It hasn't progress over years , but you can have a rough idea how to use & make your own library.
Cheers