计算化学公社

 找回密码 Forget password
 注册 Register
Views: 4710|回复 Reply: 8
打印 Print 上一主题 Last thread 下一主题 Next thread

[Python] Python中如何跨文件使用全局变量?

[复制链接 Copy URL]

490

帖子

2

威望

4877

eV
积分
5407

Level 6 (一方通行)

跳转到指定楼层 Go to specific reply
楼主
想请教一下,大家在写Python代码时,是如何跨文件使用全局变量的?

我在网上所查到的资料是:在A文件中定义global_var字典,并定义get_var(获取变量)和set_var(给变量赋值)函数,然后在B文件中如果需要设置全局变量就用set_var('xxx',xxx),如果要获取某个变量值,就用get_var('XXX').

3098

帖子

28

威望

1万

eV
积分
16892

Level 6 (一方通行)

2#
发表于 Post on 2018-10-24 11:11:20 | 只看该作者 Only view this author
本帖最后由 liyuanhe211 于 2018-10-24 11:12 编辑

这解决方案是啥意思,看不懂,还定义俩函数干啥
  1. A.py:
  2. ----------------------------
  3. ha='蛤'
  4. ----------------------------

  5. B.py:
  6. ----------------------------
  7. from A import ha
  8. print(ha,ha,sep="")
  9. ----------------------------

  10. Output:
  11. ----------------------------
  12. 蛤蛤
  13. ----------------------------
复制代码

评分 Rate

参与人数
Participants 2
eV +6 收起 理由
Reason
jitou11 + 5 暴力
niobium + 1 蛤蛤

查看全部评分 View all ratings

403

帖子

4

威望

2874

eV
积分
3357

Level 5 (御坂)

3#
发表于 Post on 2018-10-24 11:58:24 | 只看该作者 Only view this author
本帖最后由 万里云 于 2018-10-24 17:57 编辑

楼主是指类似Fortran那种在模块里定义的数据?

python中没有与之对应的概念,全局作用域其实是模块作用域,局部作用域是每个函数的作用域,不存在跨模块的全局作用域。这一点和C/Fortran不一样。举个例子:

设有一个模块foo,里面定义一个全局变量bar并初始化为10,同时定义一个函数print_bar()输出bar的值
  1. foo.py
  2. -----------------------------------------------------------
  3. bar = 10

  4. def print_bar():
  5.         print(bar)
复制代码


然后导入模块foo并将bar赋值为11,再调用函数print_bar()
  1. main.py
  2. ---------------------------------
  3. from foo import bar, print_bar
  4. bar = 11
  5. print_bar()

复制代码

可以看到输出结果仍然是10
  1. [yhli@storage ~]$ python main.py
  2. 10
复制代码


这和python的赋值机制有关。python中的变量名对应的英文是“name”,而C/C++/Fortran中变量名是“identifier”。这其中有些微妙的差别,就好比一个人可以有很多个名字,但只能有一个身份证号。Python中的赋值操作实际上是“贴标签”,先检查等号右边的对象是否存在,如果不存在就创建它,然后把左边的name贴在这个对象上。a = b = [1, 2, 3]之后再修改b,a也会跟着变,因为a和b是贴在同一个列表对象上的两个标签,而不是两个独立的对象。

再回头看模块foo中全局变量bar。在python中,放到模块作用域中的语句会被当作初始化语句,所以在导入模块过程中就在foo中创建了一个整形对象10,并贴了一个"bar"的标签在上面。导入完成后,主程序(其实是__main__模块)知道自己的作用域中有个标签叫bar,被贴在10上。这种情况下执行bar = 11,实际上是把__main__模块中的bar贴在了11上,而foo中的bar还贴在10上

要怎样才能修改foo中的bar呢?需要这样操作
  1. main.py
  2. -----------------------------------------
  3. import foo
  4. foo.bar = 11
  5. foo.print_bar()

  6. [yhli@storage ~]$ python main.py
  7. 11
复制代码
和前一个版本的main.py不同的是,导入foo过程中也会创建整型对象10并贴上bar这个标签,但导入完成后__main__中并没有bar。通过模块名来修改bar的值,实际上是新建了一个整形对象11,并把foo中的bar贴在了上面。


对于习惯了C/C++/Fortran等语言的人来说,这种赋值模式简直违反直觉。如果不对这种模式烂熟于心,很容易写出有BUG的python程序。


编程语言的语法规则一定程度上限制了程序的设计模式。Fortran就是简单直白:计算过程中需要用到一大堆数组,所以在程序开头就一股脑地把它们全部定义好。有些操作重复率较高,就拿出来做成子程序。子程序间传参数太麻烦,就把通用的一些数组放到模块中,谁要用就声明一下。而在C++/python中,把数据和操作数据的函数打包成一个类更方便。

fortran这种模式不利于代码复用。把数据和函数打包成一个类,直接导入这个类就行了。fortran这种模式还得把这些包含变量的模块带过去,零零碎碎的很容易出错。

其实我到现在都没搞懂怎样使用module中的变量才安全。这种变量有点类似C语言中的全局变量,初始化、修改、引用和内存回收都要很谨慎。目前想到的方法是每个含有变量的模块都定义xxxx_init和xxxx_finalize两个子程序,统一在主程序中调用,或者在上一级子程序调用。


评分 Rate

参与人数
Participants 1
eV +2 收起 理由
Reason
卡开发发 + 2 我很赞同

查看全部评分 View all ratings

490

帖子

2

威望

4877

eV
积分
5407

Level 6 (一方通行)

4#
 楼主 Author| 发表于 Post on 2018-10-24 13:39:58 | 只看该作者 Only view this author
万里云 发表于 2018-10-24 11:58
楼主指的是像Fortran中在module里定义的数据那样的么?

python中没有对应的概念。Python中的global scop ...

嗯。就是觉得Fortran把变量定义在module里面,然后直接use module这种方式非常方便。所以想问问看Python是否也有这种方式。

490

帖子

2

威望

4877

eV
积分
5407

Level 6 (一方通行)

5#
 楼主 Author| 发表于 Post on 2018-10-24 13:41:10 | 只看该作者 Only view this author
liyuanhe211 发表于 2018-10-24 11:11
这解决方案是啥意思,看不懂,还定义俩函数干啥

如何在B.py里面修改了ha的值(或者说get到ha的值),那么想在C.py里面使用该值,如何处理?

403

帖子

4

威望

2874

eV
积分
3357

Level 5 (御坂)

6#
发表于 Post on 2018-10-24 14:32:54 | 只看该作者 Only view this author
让你变成回忆 发表于 2018-10-24 13:41
如何在B.py里面修改了ha的值(或者说get到ha的值),那么想在C.py里面使用该值,如何处理?

看如何修改了。

如果在B.py中修改ha的方式是重新赋值(ha = xxxx),那修改后的值只在B中可见,无法传递至其它模块。

如果ha是字典或列表,增删或者修改某个元素,可以传递至其它模块。

490

帖子

2

威望

4877

eV
积分
5407

Level 6 (一方通行)

7#
 楼主 Author| 发表于 Post on 2018-10-24 14:49:42 | 只看该作者 Only view this author
万里云 发表于 2018-10-24 14:32
看如何修改了。

如果在B.py中修改ha的方式是重新赋值(ha = xxxx),那修改后的值只在B中可见,无法传 ...

嗯。我目前采用的就是第二种方式,处理成字典。

185

帖子

1

威望

4133

eV
积分
4338

Level 6 (一方通行)

8#
发表于 Post on 2018-10-24 15:37:32 | 只看该作者 Only view this author
本帖最后由 highlight 于 2018-10-24 16:05 编辑
让你变成回忆 发表于 2018-10-24 13:41
如何在B.py里面修改了ha的值(或者说get到ha的值),那么想在C.py里面使用该值,如何处理?

这样?
  1. A.py:
  2. ----------------------------
  3. ha='蛤'
  4. ----------------------------

  5. B.py:
  6. ----------------------------
  7. import A


  8. def change_ha():
  9.     A.ha = '苟'
  10.     print('change')
  11. ----------------------------
  12. C.py
  13. ----------------------------
  14. import A,B


  15. print(A.ha)
  16. B.change_ha()
  17. print(A.ha)
  18. ---------------------------
  19. Output:
  20. ---------------------------

  21. change

复制代码

3098

帖子

28

威望

1万

eV
积分
16892

Level 6 (一方通行)

9#
发表于 Post on 2018-10-24 16:01:00 | 只看该作者 Only view this author
让你变成回忆 发表于 2018-10-24 13:41
如何在B.py里面修改了ha的值(或者说get到ha的值),那么想在C.py里面使用该值,如何处理?

能不能给出一个使用案例,假设你的操作在一个文件里进行,你想实现什么过程?

本版积分规则 Credits rule

手机版 Mobile version|北京科音自然科学研究中心 Beijing Kein Research Center for Natural Sciences|京公网安备 11010502035419号|计算化学公社 — 北京科音旗下高水平计算化学交流论坛 ( 京ICP备14038949号-1 )|网站地图

GMT+8, 2024-11-24 00:45 , Processed in 0.220622 second(s), 22 queries , Gzip On.

快速回复 返回顶部 返回列表 Return to list