【剑指offer】序列化二叉树(python)
1. python的嵌套函数, 闭包和函数工厂是嵌套函数最重要的用处。如果你看到一个带装饰器的函数,这个装饰器就是一个函数工厂,它以一个函数作为参数,并返回一个新的函数,新的函数使用闭包包括了作为参数的函数。换句话说,装饰器就是一个语法糖,语法糖就是一种便捷写法。
- 嵌套函数封装了一些函数过程,对于全局命名空间来说,它们是隐藏的。
- 嵌套函数可以避免自我重复。在大型函数中,可能会重复使用一些代码,比方说,我们写一个处理文件的函数,同时支持文件名或文件对象作为参数:
def process(file_name): def do_stuff(file_process): for line in file_process: print(line) if isinstance(file_name, str): with open(file_name, 'r') as f: do_stuff(f) else: do_stuff(file_name)
- 嵌套函数作为闭包和工厂函数。闭包可以使内部函数记住它所在空间的具体状态。准确地说,应该是内部函数制造了闭包。所谓闭包,所“封闭”的是函数帧中的局部变量。
def generate_power(number): # 定义内部函数 def nth_power(power): return number ** power # 将函数作为外部函数的结果返回 return nth_power
上述代码,generate_power() 是一个工厂函数,每次调用它时,会返回一个新创建的函数,
""" Examples of use: >>> raise_two = generate_power(2) >>> raise_three = generate_power(3) >>> print(raise_two(7))# 2的7次方 128 >>> print(raise_three(5))# 3的5次方 243 """
raise_two、raise_three 指向的是这些新创建的函数;这些新创建的函数,需要一个参数 power,返回的值是 number**power;
那么,这个 number 的值是怎么来的呢?这就是闭包发生作用的地方:nth_power()函数是从外部函数,即工厂函数获取number的值的。整个过程可以分解步骤如下:
- 调用外部函数:generate_power(2);
- 创建函数 nth_power(),它需要一个参数 power;
- 保存 nth_power() 函数帧的状态,其中包括 number=2;
- 将保存的函数帧状态传递给 generate_power() 函数;
- 返回 nth_power() 函数;
闭包为 nth_power() 函数提供了初始化数据并将它返回。因此,我们调用这个被返回的函数时,总是可以在其函数帧中找到 number=2。
2. 工厂函数。工厂函数看上去像个函数,其实是类,调用它时实际上生产了该类的一个实例,就像工厂生产货物。
3. 装饰器
以上函数用装饰器写法。装饰器就是一个语法糖,它的基本流程其实和上面所举的 generate_power() 的例子是一致的。
def generate_power(exponent): def decorator(f): def inner(*args): result = f(*args) return exponent**result return inner return decorator @generate_power def raise_two(n): return n print(raise_two(7)) @generate_power def raise_three(n): return n print(raise_two(5))
解题思路:
树的序列化:先序遍历,“#”表示占位,当前值加下划线‘_’
树的反序列化:利用闭包的特性,加上队列弹出的优点。
时间:19ms,打败91%的代码
# -*- coding:utf-8 -*- # class TreeNode: # def __init__(self, x): # self.val = x # self.left = None # self.right = None class Solution: def Serialize(self, root): # write code here if not root: return '#' re = str(root.val) re += '_' + self.Serialize(root.left) re += '_' + self.Serialize(root.right) return re def Deserialize(self, s): # 嵌套函数,闭包 def des(lis): if not lis: return None v = lis.pop(0) if v == '#': return None else: head = TreeNode(int(v)) head.left = des(lis) head.right = des(lis) return head lis = s.split('_') return des(lis)
时间:20ms,打败86%的代码
不使用闭包的代码:
# -*- coding:utf-8 -*- # class TreeNode: # def __init__(self, x): # self.val = x # self.left = None # self.right = None class Solution: def Serialize(self, root): # write code here if not root: return '#' res = str(root.val) res += ','+self.Serialize(root.left) res += ','+self.Serialize(root.right) return res def Deserialize(self, s): lis = s.split(',') return self.des(lis) def des(self,lis): if not lis: return None v = lis.pop(0) if v == '#': return None else: head = TreeNode(int(v)) head.left = self.des(lis) head.right = self.des(lis) return head