本文主要总结python中的全局变量、局部变量和函数调用时的可变对象的使用:
1、关于全局变量和局部变量
(1)如果函数内无global关键字,优先读取局部变量,无局部变量则读取全局变量,不能对全局变量重新赋值。
name = 'jack'
def change_name():
name = 'john'
print(name)
change_name()
print(name)
输出:
john
jack
(2)如果函数中有global关键字,可以读取或者重新给全局变量赋值。
name = 'jack'
def change_name():
global name # 修改全局变量
name = 'john'
print(name)
change_name()
print(name)
输出:
john
john
(3)修改全局变量和修改上一级变量
修改全局变量:
name = 'Jack'
def one():
name = 'Tom'
def two():
global name
name = 'Jarry'
two()
print(name)
print(name)
one()
print(name)
输出:
Jack
Tom
Jarry
修改上一级变量:
name = 'Jack'
def one():
name = 'Tom'
def two():
nonlocal name #修改上一级变量
name = 'Jarry'
two()
print(name)
print(name)
one()
print(name)
输出:
Jack
Jarry
Jack
2、关于函数调用时的可变对象的使用:
(1)对于可变对象可以对内部元素进行操作,相当于传引用
name = ['jack', 'john']
def change_name():
name.append('tom')
print(name)
change_name()
print(name)
输出:
['jack', 'john', 'tom']
['jack', 'john', 'tom']
(2)递归程序中的使用
首先,看一下在C++中,如何在递归调用中使用全局变量或者函数参数:
在编写递归函数时,我们可以选择使用全局变量,也可以选择使用函数参数。这两者的差别在于:
- 使用全局变量:递归结束后必须对该变量修改,恢复原值;
- 使用函数参数:因为递归调用函数时,实际上,从内存分布上看,每一层调用都保存了该层函数的参数,因此递归返回上层时,不会影响原参数值。
从一个题目看下两者的区别:
题目:求二叉树中和为某一值的路径。
使用全局变量:
int currentSum = 0;
vector<Node *> path;
void traverse(Node *root, int expectedNum) {
if(root==NULL) return;
currentSum += root->value;
path.push_back(root);
// 如果是叶节点,并且路径上结点的和等于输入的值
if(root->left == NULL && root->right == NULL) {
if(currentSum == expectedNum) {
show(path);
cout << currentSum <<endl;
}
}
traverse(root->left, expectedNum);
traverse(root->right, expectedNum);
// 必须恢复,所有函数调用使用同一个值
currentSum -= root->value;
path.pop_back();
}
使用普通的函数参数:
void traverse(Node *root, int currentSum, vector<Node *> path, int expectedNum) {
if(root==NULL) return;
currentSum += root->value;
path.push_back(root);
//如果是叶节点,并且路径上结点的和等于输入的值
if(root->left == NULL && root->right == NULL) {
if(currentSum == expectedNum) {
show(path);
cout << currentSum <<endl;
}
}
traverse(root->left, currentSum, path, expectedNum);
traverse(root->right, currentSum, path, expectedNum);
// 不必恢复 currentSum, path, 各函数调用层独立使用
}
python中使用可变对象:
class TreeNode:
def init(self, x):
self.val = x
self.left = None
self.right = None
class Solution:
def __init(self):
self.result = []
def find_path(self, node, sum):
"""输入一个二叉树和一个整数,打印出二叉树中节点值的和等于输入整数所有的路径"""
if node is None:
return
stack = []
path_sum = 0
self.find_sum_core(node, sum, stack, path_sum)
print(stack)
print(path_sum)
def find_sum_core(self, node, sum, stack, path_sum):
stack.append(node.val) # 相当于全局变量,需手动恢复现场
path_sum += node.val # 局部变量,递归自动保护现场
if node.left is None and node.right is None:
if path_sum == sum:
self.result.append(copy.deepcopy(stack))
if node.left is not None:
self.find_sum_core(node.left, sum, stack, path_sum)
if node.right is not None:
self.find_sum_core(node.right, sum, stack, path_sum)
# 返回上层前要恢复现场
stack.pop(-1)
if __name__ == '__main__':
node1 = TreeNode(1)
node2 = TreeNode(2)
node3 = TreeNode(3)
node4 = TreeNode(4)
node5 = TreeNode(7)
node6 = TreeNode(6)
node7 = TreeNode(7)
node1.left = node2
node1.right = node3
node2.left = node4
node2.right = node5
node3.left = node6
node3.right = node7
print("****** Test the path of sum is target: ******")
S = Solution()
S.find_path(node1, 10)
print(S.result)
输出:
****** Test the path of sum is target: ******
[[1, 2, 7], [1, 3, 6]]