generics/模板在Python?
python如何处理generics/模板types的场景? 说我想创build一个外部文件“BinaryTree.py”,并处理二叉树,但任何数据types。
所以我可以将它传递给一个自定义对象的types,并有一个该对象的二叉树。 这是怎么做到的Python?
Python使用鸭子打字 ,所以它不需要特殊的语法来处理多种types。
如果您来自C ++的背景,那么您将会记得,只要模板函数/类中使用的操作是在某个typesT
(在语法级别)上定义的,就可以在模板中使用该typesT
所以,基本上,它的工作原理是一样的:
- 定义您想要在二叉树中插入的项目types的合约。
- logging这个合同(即在类文件中)
- 仅使用合约中指定的操作来实现二叉树
- 请享用
但是你会注意到,除非你写明确的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立自己的图书馆。
干杯
看看内置的容器是如何做到的。 dict
和list
等包含您喜欢的任何types的异构元素。 如果你为你的树定义了一个insert(val)
函数,它会在某个时刻执行类似于node.value = val
而Python将负责其余的操作。