snmpset对象不可写_[Python]可变对象与多进程通信

一、可变对象与不可变对象

参考Python 的函数是怎么传递参数的?

具体看文档就行了,这里引用文章的结论:

1.对于不可变对象作为函数参数,相当于C系语言的值传递;
2.对于可变对象作为函数参数,相当于C系语言的引用传递;

另外有评论指出,Python中的函数通过引用传参,只不过对于不可变对象,会创建新的对象,并将原来的变量名绑定到新的对象上。

另外有一个哥们喋喋不休在评论这么一段代码:

ls = [1,2,3]

def test(list):

······ list = []

test(ls)

print(ls)

说实话我也很懵逼,为什么没有改变?后来发现还是这哥们对Python不熟悉啊,如果对命名空间了解多一点就不会问这个了,我可以写这一段代码:

def test1(listA):
	print ("id(listA) = %s" % id(listA))
	listA.append(4)

	listA = []
	print ("id(listA) = %s" % id(listA))

def test():
	ls = [1, 2, 3]
	print ("id(ls) = %s" % id(ls))
	test1(ls)
	print ("After test1, ls = %s" % ls)

输出的结果是:

id(ls) = 140407795100040
id(listA) = 140407795100040
id(listA) = 140407795131528
After test1, ls = [1, 2, 3, 4]

可见用内置方法还是可以改变的,listA这个变量开始是绑定到id为140407795100040即与ls相同的内存上,这种情况是可以用内置方法进行操作的,如果重新赋值成空列表相当于把变量listA绑定到另一块内存上。

ps.如果想清空该列表可以用内置方法clear(),以下为实验过程:

def test2(listA):
	listA.clear()
	print ("id(listA) = %s" % id(listA))

def test():
	ls = [1, 2, 3]
	print ("id(ls) = %s" % id(ls))

	test2(ls)
	print ("After test1, ls = %s" % ls)

输出的结果是:

id(ls) = 140632970701192
id(listA) = 140632970701192
After test1, ls = []

一篇写的不错的文章:Python的函数参数传递:传值?引用?

我的结论:传参传的都是变量名,如果在函数体内能改变变量名指向的对象,那么该变量名指向的是可变对象,如果改变不了,那么指向的是不可变对象。

最后纯记录一下Python命名空间的知识,可参考Python命名空间的本质 - windlaughing - 博客园。

命名空间查找顺序:

1.局部命名空间:记录了函数的变量,包括函数的参数和局部定义的变量,可使用locals()访问,只读(这个存疑,官方文档位于Python locals() - Python Standard Library););

2.全局命名空间:记录了模块的变量,包括函数、类、其它导入的模块、模块级的变量和敞亮,可使用globals()进行访问,可修改【全局命名空间里的函数似乎可以直接访问,变量则需要通过globals()["变量名"]访问,这点待考证】;

3.内置命名空间:任何模块均可访问它,它存放着内置的函数和异常;

4.如果Python查找不到,会抛出NameError异常;

del()函数只是在命名空间里删掉该变量,并不会清空内存。


二、在多进程中的可变对象

在Python中使用多进程我用的是multiprocessing库,可以参考多进程。

具体的问题是:我在主进程中生成一个字典(可变对象),并启动两个子进程,传字典进去,那么在其中一个子进程中改变这个可变对象会不会影响另外一个子进程的值。

以下是实验代码:

from multiprocessing import Process
import time

# 写数据进程执行的代码:
def write(dictTest):
	while True:
		dictTest["Hello"] += 1
		print ("In function write(), id(dictTest) = %s" % id(dictTest))
		print ("In function write(), dictTest = %s" % dictTest)
		time.sleep(1)

# 读数据进程执行的代码:
def read(dictTest):
	while True:
		print ("In function read(), id(dictTest) = %s" % id(dictTest))
		print ("In function read(), dictTest = %s" % dictTest)
		time.sleep(1)

if __name__=='__main__':
	dictTest = {"Hello":1}
	pw = Process(target=write, args=(dictTest,))
	pr = Process(target=read, args=(dictTest,))
	# 启动子进程pw,写入:
	pw.start()
	# 启动子进程pr,读取:
	pr.start()
	# 等待pw结束:
	pw.join()
	# pr进程里是死循环,无法等待其结束,只能强行终止:
	pr.terminate()

原理很简单,写数据进程不断给字典赋一个新的值,读数据进程则不断读出新的值,以下为实验结果:

(python36) dao@dao:~/project/test$ python testMultiProcessing.py 
In function write(), id(dictTest) = 140319281161848
In function write(), dictTest = {'Hello': 2}
In function read(), id(dictTest) = 140319281161848
In function read(), dictTest = {'Hello': 1}
In function write(), id(dictTest) = 140319281161848
In function write(), dictTest = {'Hello': 3}
In function read(), id(dictTest) = 140319281161848
In function read(), dictTest = {'Hello': 1}
In function write(), id(dictTest) = 140319281161848
In function write(), dictTest = {'Hello': 4}
In function read(), id(dictTest) = 140319281161848
In function read(), dictTest = {'Hello': 1}
In function write(), id(dictTest) = 140319281161848
In function write(), dictTest = {'Hello': 5}
In function read(), id(dictTest) = 140319281161848
In function read(), dictTest = {'Hello': 1}
In function write(), id(dictTest) = 140319281161848
In function read(), id(dictTest) = 140319281161848
In function read(), dictTest = {'Hello': 1}
In function write(), dictTest = {'Hello': 6}
In function read(), id(dictTest) = 140319281161848
In function read(), dictTest = {'Hello': 1}

可以看出,虽然两者的ID数是一样的,表明两者在内存是一体的,但是两者的数却发生了变化,原因待以后察觉吧。


三、多进程通信

如果我们需要在多进程之间通信,比如改变子进程之间的公共字典,可以使用Manager管理的共享数据类型,可以参考Python多进程编程-进程间共享数据(Value、Array、Manager)。

这里放一个我的测试程序:

(python36) dao@dao:~/project/test$ python testMultiProcessing.py 
In function read(), id(dictTest) = 140054398564280
In function write(), id(dictTest) = 140054398564280
In function write(), dictTest = {'Hello': 2}
In function read(), dictTest = {'Hello': 2}
In function read(), id(dictTest) = 140054398564280
In function write(), id(dictTest) = 140054398564280
In function read(), dictTest = {'Hello': 3}
In function write(), dictTest = {'Hello': 3}
In function read(), id(dictTest) = 140054398564280
In function read(), dictTest = {'Hello': 3}
In function write(), id(dictTest) = 140054398564280
In function write(), dictTest = {'Hello': 4}
In function read(), id(dictTest) = 140054398564280
In function read(), dictTest = {'Hello': 4}
In function write(), id(dictTest) = 140054398564280
In function write(), dictTest = {'Hello': 5}
In function read(), id(dictTest) = 140054398564280
In function read(), dictTest = {'Hello': 5}
In function write(), id(dictTest) = 140054398564280
In function write(), dictTest = {'Hello': 6}
In function read(), id(dictTest) = 140054398564280
In function read(), dictTest = {'Hello': 6}
In function write(), id(dictTest) = 140054398564280
In function write(), dictTest = {'Hello': 7}
In function read(), id(dictTest) = 140054398564280
In function read(), dictTest = {'Hello': 7}

可以看出,这个是符合使用要求的。

【已完结】

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值