在Haskell中,我可以定义一个二叉树如下:
data Bint a = Leaf a | Branch a (Bint a) (Bint a)
然后我可以对它进行一些操作如下:
height (Leaf a) = 1
height (Branch a l r) = 1 + (max (height l) (height r))
count (Leaf a) = 1
count (Branch a l r) = 1 + (count l) + (count r)
我知道Python在Haskell中没有data
的等价物。如果有,请告诉我。
那么,如何在Python中定义二叉树,以及如何在其中实现上述两个函数?
5条答案
按热度按时间wnrlj8wa1#
我在这里使用的是一个类似于Haskell的函数式编程。从某种意义上说,这不是非常“Python”。特别是,它不是面向对象的。尽管如此,它仍然很有用,也很干净。
数据类型是一个类。具有多个数据构造函数的数据类型是一个具有关于如何构造的额外信息的类。当然,它需要一些数据。使用构造函数来确保所有树都是法律的的:
这个构造函数调用起来有点不方便,所以有一些智能的构造函数很容易用途:
我们如何得到这些值呢?让我们也做一些帮助程序:
就是这样。你得到了一个纯“代数”数据类型,可以用函数访问:
8yparm6h2#
最接近的可能是带有方法的类:
虽然这有点习惯,也有自己的优点,但它也缺乏Haskell版本的一些品质。最重要的是,函数定义必须与类沿着定义,在同一个模块中。您可以使用single-dispatch generic functions而不是方法来恢复。结果比方法和Haskell函数都更开放。并且在有益时允许将定义扩展到多个模块。
lvmkulzt3#
Python不像Haskell那样有“数据构造器”的概念。你可以像大多数其他OOP语言一样创建类。或者你可以总是用内置的函数来表示你的数据类型,只定义处理它们的函数(这是在
heapq
内置模块中实现堆的方法)。python和haskell之间的差异是巨大的,所以最好避免在haskell和python的语法/功能之间进行严格的比较,否则你最终会写出非pythonic和低效的python代码。
即使python确实有一些函数式的特性,它也不是一种函数式语言,所以你必须完全改变你的程序的范式来获得可读的,pythonic的和高效的程序。
使用类的可能实现可以是:
代码可以简化一点,为
left
和right
提供一个“更智能”的默认值:注意,这些实现允许节点只有一个子节点。
然而,你并不一定要使用类来定义数据类型。例如,你可以说
Bint
可以是一个单一元素的列表,根的值,或者是一个有三个元素的列表:值,左孩子和右孩子。在这种情况下,您可以将函数定义为:
另一种方法是使用
namedtuple
s:smdncfj34#
五年了,我的答案是。
将
data Tree a = Leaf a | Branch (Tree a) (Tree a) deriving (Show)
转换为Python...不带类型检查(更像python)
带类型检查(更像Haskell)
Tree类的
height
、count
方法Leaf和分支类的
height
、count
方法height
,count
类外方法(最像haskell)pepwfjgg5#
使用最现代的Python习惯用法的答案是,您需要:
frozen=True
定义不变性的数据类这个答案的优点是:
isinstance
),以使代码读取更简单、更高效Leaf, Branch
的超类时,可以进行穷举检查,因此如果match
没有警告输入,则程序是正确的。