# python 学习:各种类之间循环引用,以及参数传递

2013-05-07 19:03:06 +08:00
 Hualin
今天做了个实验,代码是这样的:

=== data.py ===

class Data:
def __init__(self):
self.base_x = 123

=== plugin.py ===

class Plugin:
def __init__(self, para, data):
self.para = para
self.data = data
self.data.para = para

def remove(self):
del self.data.para

=== main.py ===

from data import Data
from plugin import Plugin

dd = Data()
pp = Plugin(999, dd)

print dd.base_x
print dd.para

pp.remove()
print dd.para

== 输出结果是这样的:==
123
999

Traceback (most recent call last):

File "C:\test\main.py", line 11, in <module>
print dd.para
AttributeError: Data instance has no attribute 'para'
[Finished in 0.1s with exit code 1]

那么 Plugin 的对象 pp 的初始化函数参数 data,实际上是 Data 类 dd 的实际指针。所以我执行 del self.data.para 后 dd 也就没有这个属性了。

这样的话 pp.data 实际和 main 中的 dd 指向的都是同一个对象。

请问各位 v2exer 们,有关 python 传递参数这种对象循环传递,以及函数参数是引用还是拷贝的知识在哪里能有介绍?

欢迎讨论
4124 次点击
所在节点    Python
10 条回复
raquelken
2013-05-08 16:25:45 +08:00
既不是引用也不是拷贝,参数名字就真的只是名字而已,关键是你例子里面的pp.data和main的dd是同一个对象,而且Data是可修改的(mutable)
所以你可以修改pp.data的para属性,也就是dd的para属性
http://effbot.org/zone/python-objects.htm
Idiosyncratic
2013-05-09 15:46:53 +08:00
@raquelken 我感觉,lz想问的是参数传递的方式而不是object的底层实现啊。。,

其实按照那片文章的意思,所有的名字其实都是一种 对于对象的指针(比喻而已,暂时想不到更贴切的),那么所有的参数传递应该都可以视为引用传递
thedevil5032
2013-05-09 16:24:11 +08:00
函数参数是引用还是拷贝的知识在哪里能有介绍?

其实这个问题的关键在于,你的参数是什么类型的。(貌似是这样的)

http://docs.python.org/2/library/copy.html

####
a = 1
b = 1
id(a) == id(b)

# 自己的一点理解
# 通常赋值一个常量对象,实际上是把一个常量名和内存中的一个值联系起来了。
# 但是如果是集合型的对象(list,dict等,具体参照上面的链接),则有时会是复制,有时则是“链接”。
raquelken
2013-05-09 16:48:02 +08:00
@Idiosyncratic 如果是引用的话,如何用python实现这个呢?
void addone(int &in) {
in ++;
}

int main(int argc, char const *argv[])
{
int in = 1;
addone(in);
return 0;
}
yuelang85
2013-05-09 17:23:59 +08:00
可以使用id函数来测试。

python中,没有传递值,任何时候都是传递指针。
>>> def a(x, y):
..._____print id(x), id(y)
..._____x.append(1)
..._____y+=1
..._____print id(x), id(y)
...

>>> x = []
>>> y = 0

>>> id(x), id(y)
(4547969608, 140234989831872)

>>> a(x, y)
4547969608 140234989831872
4547969608 140234989831848
>>>


int,str是不可变对象,自身不能改变,所以修改的时候会产生新对象。而list,dict等可以修改自身
Idiosyncratic
2013-05-09 17:42:01 +08:00
@raquelken 嗯,那也是,所以说,我觉得那片文章讲的只是python底层object和name的如何绑定的关系,并没有解释参数传递的方式;具体在参数传递上应该还是和其他面向对象语言很像,要看对象的类型,值类型就值传递(int,或是C#里的struct),引用类型就引用传递;
以上只是猜测哈,我没仔细研究过python,不过感觉用着像是这么回事
timonwong
2013-05-09 19:48:07 +08:00
@Idiosyncratic
传递方式与java类似,属于“值传递"(只是python没有primitive types,所有的值传递传递的都是**对象的引用**)
yuelang85
2013-05-09 19:51:34 +08:00
@Idiosyncratic

看看我的回复。。。。

python根本就没有值传递。

如果你想传递值,只能生成一个新对象
Idiosyncratic
2013-05-09 20:55:57 +08:00
@yuelang85 嗯,学习了,试了一下@yuelang85的测试,的确是这样的。多谢!!
yuelang85
2013-05-09 21:04:47 +08:00
@Idiosyncratic 客气。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/68063

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX