鱼C论坛

 找回密码
 立即注册
查看: 1142|回复: 2

全局变量的理解

[复制链接]
发表于 2019-4-9 10:37:11 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
  1. def plot_tree(my_tree, parant_pt, node_txt):
  2.     """
  3.     函数作用:
  4.     :param my_tree: 决策树
  5.     :param parant_pt: 父节点
  6.     :param node_txt: 结点文本标签信息
  7.     :return:
  8.     """
  9.     # 计算叶节点
  10.     num_leafs = get_num_leafs(my_tree)
  11.     # 计算深度
  12.     depth = get_tree_depth(my_tree)
  13.     # 第一个判断节点
  14.     first_str = list(my_tree.keys())[0]
  15.     # 初始化子节点的位置
  16.     # 全局变量plot_tree.totalW存储树的宽度
  17.     # 全局变量plot_tree.totalD存储树的高度
  18.     cntr_pt = (plot_tree.xoff + (1.0 + float(num_leafs))/2.0/plot_tree.totalW,
  19.                plot_tree.yoff)
  20.     # 计算父节点和子节点的中间位置,并在此处添加文本标签信息
  21.     plot_mid_text(cntr_pt, parant_pt, node_txt)
  22.     plot_node(first_str, cntr_pt, parant_pt, decisionNode)
  23.     # 第一个判断节点的value
  24.     second_dict = my_tree[first_str]
  25.     # 按比例减少全局变量plot_tree_yoff
  26.     plot_tree.yoff = plot_tree.yoff - 1.0/plot_tree.totalD
  27.     # 遍历second_dict.keys(),绘制子节点(可以是叶子结点,或判断节点)
  28.     for key in second_dict.keys():
  29.         # key对应的value的类型是字典(说明是判断节点),则递归调用函数
  30.         # 否则(说明是叶子节点),增加X的偏移,绘制箭头,并计算中间位置,添加文本信息
  31.         if type(second_dict[key]).__name__ == 'dict':
  32.             plot_tree(second_dict[key], cntr_pt, str(key))
  33.         else:
  34.             plot_tree.xoff = plot_tree.xoff + 1.0/plot_tree.totalW
  35.             plot_node(second_dict[key], (plot_tree.xoff, plot_tree.yoff),
  36.                       cntr_pt, leafNode)
  37.             plot_mid_text((plot_tree.xoff, plot_tree.yoff), cntr_pt, str(key))
  38.     # 绘制完所有子节点之后,增加全局变量Y的偏移
  39.     plot_tree.yoff = plot_tree.yoff + 1.0/plot_tree.totalD
复制代码


如上是一部分代码,可以运行成功,但是有个问题,plot_tree.yoff和plot_tree.xoff都是全局变量,注意这里是点(.)。
之前我的理解就是,plot_tree.yoff和plot_tree.xoff就是一个变量(一个代号),于是我将其改为plot_tree_yoff和plot_tree_xoff(把点改为下划线),
但是这样会设计到全局变量和局部变量的问题,有部分plot_tree.yoff和plot_tree.xoff显示未“灰色”,所以这就表明这不是一个简单的变量。
望解惑,谢谢。
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2019-4-9 17:49:19 | 显示全部楼层
外部定义的变量,如果在函数内部重新去定义或者引用这个同名变量的时候,python是在内存中开辟一个新的内存地址来保存这个变量,但是两个同名的变量在内存中指向的地址是不同的。
如果需要在函数内部修改外部全局变量需要用global来声明该变量非局部变量。如:
>>> num = 1
>>> id(num)
1679083648
>>> def func():
        global num
        num = 2
        print(id(num))
        print(num)

       
>>> id(num)
1679083648
>>> func()
1679083664
2
>>> num
2
>>>
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-4-10 09:32:25 | 显示全部楼层
万中山 发表于 2019-4-9 17:49
外部定义的变量,如果在函数内部重新去定义或者引用这个同名变量的时候,python是在内存中开辟一个新的内存 ...

你说的这种全局变量和局部变量,我是知道的,我说的不是这个意思。如下代码:
  1. def plot_tree(my_tree, parant_pt, node_txt):
  2.     """
  3.     函数作用:
  4.     :param my_tree: 决策树
  5.     :param parant_pt: 父节点
  6.     :param node_txt: 结点文本标签信息
  7.     :return:
  8.     """
  9.     # 计算叶节点
  10.     num_leafs = get_num_leafs(my_tree)
  11.     # 计算深度
  12.     depth = get_tree_depth(my_tree)
  13.     # 第一个判断节点
  14.     first_str = list(my_tree.keys())[0]
  15.     # 初始化子节点的位置
  16.     # 全局变量plot_tree.totalW存储树的宽度
  17.     # 全局变量plot_tree.totalD存储树的高度
  18.     cntr_pt = (plot_tree.xoff + (1.0 + float(num_leafs))/2.0/plot_tree.totalW,
  19.                plot_tree.yoff)
  20.     # 计算父节点和子节点的中间位置,并在此处添加文本标签信息
  21.     plot_mid_text(cntr_pt, parant_pt, node_txt)
  22.     plot_node(first_str, cntr_pt, parant_pt, decisionNode)
  23.     # 第一个判断节点的value
  24.     second_dict = my_tree[first_str]
  25.     # 按比例减少全局变量plot_tree.yoff
  26.     plot_tree.yoff = plot_tree.yoff - 1.0/plot_tree.totalD
  27.     # 遍历second_dict.keys(),绘制子节点(可以是叶子结点,或判断节点)
  28.     for key in second_dict.keys():
  29.         # key对应的value的类型是字典(说明是判断节点),则递归调用函数
  30.         # 否则(说明是叶子节点),增加X的偏移,绘制箭头,并计算中间位置,添加文本信息
  31.         if type(second_dict[key]).__name__ == 'dict':
  32.             plot_tree(second_dict[key], cntr_pt, str(key))
  33.         else:
  34.             plot_tree.xoff = plot_tree.xoff + 1.0/plot_tree.totalW
  35.             plot_node(second_dict[key], (plot_tree.xoff, plot_tree.yoff),
  36.                       cntr_pt, leafNode)
  37.             plot_mid_text((plot_tree.xoff, plot_tree.yoff), cntr_pt, str(key))
  38.     # 绘制完所有子节点之后,增加全局变量Y的偏移
  39.     plot_tree.yoff = plot_tree.yoff + 1.0/plot_tree.totalD


  40. def create_plot(in_tree):
  41.     """
  42.     函数作用:创建新图形并清空绘图区,在绘图区绘制决策节点和叶节点
  43.     :param in_tree: 决策树
  44.     :return:
  45.     """
  46.     # 创建窗口
  47.     fig = plt.figure(1, facecolor='white')
  48.     # 清空绘图区
  49.     fig.clf()
  50.     # 创建空字典
  51.     axprops = dict(xticks=[], yticks=[])
  52.     # 创建子图的绘图区
  53.     create_plot.axl = plt.subplot(111, frameon=False, **axprops)
  54.     # 全局变量plot_tree.totalW存储决策树的宽度
  55.     # 全局变量plot_tree.totalD存储决策树的高度
  56.     # 全局变量plot_tree.xoff存储决策树节点的x坐标
  57.     # 全局变量plot_tree.yoff存储决策树节点的y坐标
  58.     plot_tree.totalW = float(get_num_leafs(in_tree))
  59.     plot_tree.totalD = float(get_tree_depth(in_tree))
  60.     plot_tree.xoff = -0.5/plot_tree.totalW
  61.     plot_tree.yoff = 1.0
  62.     plot_tree(in_tree, (0.5, 1.0), '')  # 决策树的起点:(0.5,1.0)
  63.     # 调用"绘制带箭头的注解"函数
  64.     # plot_node('decisionNodes', (0.5, 0.1), (0.1, 0.5), decisionNode)
  65.     # plot_node('leafNodes', (0.8, 0.1), (0.3, 0.8), leafNode)
  66.     plt.show()
复制代码


可以主要看plot_tree.yoff这个变量,两个函数都有这个变量,在create_plot()函数中初始化为1.0,然后就在plot_tree()函数中引用这个变量,值得注意的是,在这个函数中没有初始化这个变量,也没有global,可以直接引用。网盘通过debug查看plot_tree.yoff的值变化,发现plot_tree.yoff的值是从create_plot()传递到plot_tree()中的,这就有点像全局变量了
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2026-1-15 04:19

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表