generics/模板在Python?

python如何处理generics/模板types的场景? 说我想创build一个外部文件“BinaryTree.py”,并处理二叉树,但任何数据types。

所以我可以将它传递给一个自定义对象的types,并有一个该对象的二叉树。 这是怎么做到的Python?

Python使用鸭子打字 ,所以它不需要特殊的语法来处理多种types。

如果您来自C ++的背景,那么您将会记得,只要模板函数/类中使用的操作是在某个typesT (在语法级别)上定义的,就可以在模板中使用该typesT

所以,基本上,它的工作原理是一样的:

  1. 定义您想要在二叉树中插入的项目types的合约。
  2. logging这个合同(即在类文件中)
  3. 仅使用合约中指定的操作来实现二叉树
  4. 请享用

但是你会注意到,除非你写明确的types检查(通常不鼓励),否则你将无法强制二叉树仅包含所选types的元素。

其实现在你可以在Python 3.5+中使用generics了。 请参阅PEP-484并input库文档 。

根据我的实践,对于那些熟悉Javagenerics的人来说,它并不是非常无缝和清晰,但仍然可以使用。

由于python是dynamicinput的,这是非常容易的。 事实上,你不得不为BinaryTree类做额外的工作,不能使用任何数据types。

例如,如果您想要使用key()方法将对象放置在对象内的key() ,则只需在对象上调用key() 。 例如:

 class BinaryTree(object): def insert(self, object_to_insert): key = object_to_insert.key() 

请注意,你永远不需要定义什么样的类object_to_insert。 只要它有一个key()方法,它就可以工作。

如果你想让它像string或整数这样的基本数据types,就是一个例外。 你将不得不把它们包装在一个类,让他们与你的通用BinaryTree工作。 如果这听起来太重了,而且你想要额外的效率,实际上只是存储string,对不起,这不是Python擅长的。

由于Python是dynamictypes的,在许多情况下,对象的types并不重要。 接受任何东西是个好主意。

为了说明我的意思,这个树类将接受它的两个分支的任何东西:

 class BinaryTree: def __init__(self, left, right): self.left, self.right = left, right 

它可以像这样使用:

 branch1 = BinaryTree(1,2) myitem = MyClass() branch2 = BinaryTree(myitem, None) tree = BinaryTree(branch1, branch2) 

在提出pythongenericstypes的一些好的想法之后,我开始寻找其他有相同想法的人,但我找不到任何东西。 所以,在这里。 我试了一下,它运作良好。 它允许我们用python参数化我们的types。

 class List( type ): def __new__( type_ref, member_type ): class List( list ): def append( self, member ): if not isinstance( member, member_type ): raise TypeError( 'Attempted to append a "{0}" to a "{1}" which only takes a "{2}"'.format( type( member ).__name__, type( self ).__name__, member_type.__name__ ) ) list.append( self, member ) return List 

您现在可以从这个genericstypes派生types。

 class TestMember: pass class TestList( List( TestMember ) ): def __init__( self ): super().__init__() test_list = TestList() test_list.append( TestMember() ) test_list.append( 'test' ) # This line will raise an exception 

这个解决scheme是简单的,它有它的限制。 每次创buildgenericstypes时,都会创build一个新types。 因此,inheritanceList( str )作为父类的多个类将从两个单独的类inheritance。 为了克服这个问题,你需要创build一个dict来存储内部类的各种forms,并返回先前创build的内部类,而不是创build一个新类。 这将防止创build具有相同参数的重复types。 如果感兴趣,可以使用装饰器和/或元类来创build更优雅的解决scheme。

幸运的是,python中的generics编程已经有了一些工作。 有一个库: 通用

这里是它的文件: http : //generic.readthedocs.org/en/latest/

它已经没有多年的进展,但你可以有一个粗略的想法如何使用和build立自己的图书馆。

干杯

看看内置的容器是如何做到的。 dictlist等包含您喜欢的任何types的异构元素。 如果你为你的树定义了一个insert(val)函数,它会在某个时刻执行类似于node.value = val而Python将负责其余的操作。