由买买提看人间百态

boards

本页内容为未名空间相应帖子的节选和存档,一周内的贴子最多显示50字,超过一周显示500字 访问原贴
_Python版 - Other languages have "variables", Python has "names"
相关主题
如何用 Python 修改 mp3 文件的音乐标题└ Re: Re: Is it possible to use c++ objects from python co
初级问题:怎么指代上一个命令的输出Question about this python error.
Re: python .pyw问题请教An easter egg in Python :)
python程序运行速度的问题 (转载)精华区里新加了很多东西
└ Re: python程序运行速度的问题python有好的免费Linux IDE么?
Is it possible to use c++ objects from python code?新人报道,请问各位大牛如何开始学习python?
└ Re: Is it possible to use c++ objects from python code?决定现在开始好好学学python
├ Re: Is it possible to use c++ objects from python code?Google I/O 2008 - Painless Python
相关话题的讨论汇总
话题: python话题: 对象话题: prints话题: object话题: java
1 (共1页)
p**z
发帖数: 65
1
刚开始用Python不习惯,为什么传递参数的时候没有办法指定是 by reference 或者
by value。后来终于理解了,Python的变量和许多其他语言的不同,其他语言的变量名
常可以被想象成有名字的装载数据的容器,变量赋值是把数据放进容器里(即使是 by
reference,也是把指针数据放进指针变量里);Python的变量名却最好比喻为在对象
上贴上的名字标签,所以变量赋值永远是 by reference,就是在已经有的对象上添一
个标签。这个可能跟Python所有数据类型都是对象(object)有关系。
这个方法通常最有效率,但是也容易让人迷惑,因为跟一般人的编程习惯不一样。
对于 immutable 的对象(比如浮点常数,字符串常数等等),把它赋值给一个变量名
仅仅是给这个常数对象贴上新标签,常数对象本身并不能被改变。如果两个标签 A 和
B 贴在同一个常数对象上,给 A 赋新值就好像把这个标签揭下来贴到另一个不相干的
常数对象上,对 B 没有影响,所以表现好像跟 by value 传参很像,但实际上还是 by
reference 的。
但是对于 mutable 的对象(比如list,dictionary,numpy 数组,自定义的类等等)
,把它赋值给一个变量名也仅仅是给这个对象贴上新标签。但是这个对象一旦内容被改
变,贴在它上面所有标签的内容同时都会改变。也就是说,如果 A 和 B 贴在同一个对
象上,改变 A 的内容会影响 B。这个看上去又像一般的 by reference 传参了。
只要记住这个比喻,认识到Python变量赋值和传参永远是 by reference 的,就可以避
免错误。如果真的需要传递一个 mutable 对象进到函数里,希望函数改变它,但是这
个改变不传递给原本的那个对象,就需要 import copy,然后在函数里用 copy.copy()
建立一个该对象的克隆,再改变克隆,而不是改变传进来的参数本身。
这个极棒的贴标签比喻是我从这个tutorial看来的,还有图解的,很值得一看:
Code Like a Pythonista: Idiomatic Python http://python.net/~goodger/projects/pycon/2007/idiomatic/handout.html
搜索"Other languages have "variables"",大约在一半的位置。
f*******n
发帖数: 12623
2
这是一大堆bullshit。Python当然有variables。Python的variables和Java的
variables一样。只是不懂的人编造一个新的词“name”来形容他们不懂的东西。

by


【在 p**z 的大作中提到】
: 刚开始用Python不习惯,为什么传递参数的时候没有办法指定是 by reference 或者
: by value。后来终于理解了,Python的变量和许多其他语言的不同,其他语言的变量名
: 常可以被想象成有名字的装载数据的容器,变量赋值是把数据放进容器里(即使是 by
: reference,也是把指针数据放进指针变量里);Python的变量名却最好比喻为在对象
: 上贴上的名字标签,所以变量赋值永远是 by reference,就是在已经有的对象上添一
: 个标签。这个可能跟Python所有数据类型都是对象(object)有关系。
: 这个方法通常最有效率,但是也容易让人迷惑,因为跟一般人的编程习惯不一样。
: 对于 immutable 的对象(比如浮点常数,字符串常数等等),把它赋值给一个变量名
: 仅仅是给这个常数对象贴上新标签,常数对象本身并不能被改变。如果两个标签 A 和
: B 贴在同一个常数对象上,给 A 赋新值就好像把这个标签揭下来贴到另一个不相干的

p**z
发帖数: 65
3
首先,我同意 Python 里的 name 也叫做 variable。Python 自己文档里面就是混用的
。但是它的真正行为确实是一个名字,跟其他 statically typed 语言的变量有所不同
。另外,原帖中 by value 和 by reference 的表述并不准确,因为那是我以 VB.NET
的行为来打比方的,并没有严格按照这两个术语的原意。
我简单看了一下 Python 和 Java 的文档,觉得它们还是有很大不同的。
对于 Python,可以看一下它的 language reference, 3.1. Objects, values and
types, 以及 4.1. Naming and binding。如果我理解没有错的话,Python 没有简单数
据类型,所有的数据都是对象。每个对象有自己的唯一的身份(不可改变),类型(不
可改变),内容(有些 immutable,比如整数,浮点数,字符串;有些 mutable,比如
list,dictionary)。Python 是 dynamic typing 的,就是说一个名字(变量)使用
前不用声明数据类型。它的实现就是用的 name binding。一个内存里的对象可以 bind
好几个名字。如果这个对象是 mutable 的,改变这个对象的内容就改变所有名字的内
容。如果这个对象是 immutable 的,赋新值给它的名字意味着这个名字换了一个
binding,跟原来的对象没有关系了。这个可以从下面的例子看出来。
immutable 的例子: 把 a 的值 1 赋给 b,它们就 bind 到了内存中的同一个对象 1
上(从对象的相同 id 可以看出)。当给 b 赋新值 5,因为整数是 immutable 的,5
和 1 在内存里是不同的对象,所以 b bind 到了一个不同的对象 5 上,而 a 仍然
bind 在 1 上。有趣的是,如果给 c 赋值 5,你会发现 b 和 c 的 id 完全相同,就
是说不仅它们的值相等,它们在内存中根本就是同一个对象 5。这个可以用 b is c 来
检查:只有身份完全相同这个判断才是真。
>>> a = 1
>>> id(a)
40757832L
>>> b = a
>>> id(b)
40757832L
>>> b = 5
>>> id(b)
40757736L
>>> a
1
>>> c = 5
>>> id(c)
40757736L
>>> b is c
True
mutable 的例子: 把 a 的值 [1] 赋给 b,它们两个名字就 bind 到同一个对象上了
。当 b 的内容被改变(list 里唯一的内容变成了2),a 也被同样的改变了,因为它
们是同一个对象。但是如果赋值一个新的 list 给 b,这个名字的 binding 就变了,a
和 b 不再联系在一起。
>>> a = [1]
>>> id(a)
140869128L
>>> b = a
>>> id(b)
140869128L
>>> b[0] = 2
>>> b
[2]
>>> a
[2]
>>> b = [3]
>>> id(b)
114998024L
>>> a
[2]
我对于 java 了解不是很深入,但是知道它是 statically typed,每个变量必须声明
类型。如果是 primitive data types (整数,浮点数,boolean等),那么这些数据
是直接在内存中开辟位置存储的,所以 int a = 5; int c = 5; 就会分配两个整数的
内存,一个给 a,一个给 c,两个都存着同样的值 5,好像两个有标签的盒子一样,而
不是象 Python 那样 a 和 c 都指向同样的内存对象 5,好像在同一个对象 5 上贴了
两个标签。当然,对于不是 primitive data type 的 class,变量名字仅仅是
reference,虽然 java 赋值或者函数传参都是 by value 的,但是当值或者参数是一
个对象,by value 拷贝的就只是这个 reference,对象的内容并没有自动拷贝。这个
就跟 Python 赋值或传参 mutable 对象的表现类似。比如下面这个Python的例子,可
以看出函数外面原先的名字 a 没有被函数内的重新 binding 改变,因为函数内的 x
是另一个名字,当改变 x 的 binding 的时候并不改变 a 的 binding。但是如果改变
x 指向的内容,因为 x 跟 a 指向同一内存对象,函数外面 a 的内容也改变了。这个
跟 java by value 传递 reference 应该是很像的。
>>> a = [1]
>>> def change(x):
... x = [2]
...
>>> change(a)
>>> a
[1]
>>> def changecontent(x):
... x[0] = 1000
...
>>> changecontent(a)
>>> a
[1000]
参考:
http://docs.python.org/2/reference/datamodel.html#objects-value
http://docs.python.org/2/reference/executionmodel.html#naming-a
http://docs.oracle.com/javase/tutorial/java/nutsandbolts/dataty
http://www.javaworld.com/javaqa/2000-05/03-qa-0526-pass.html
如果上面理解有不对,请指正并指明出处。
f*******n
发帖数: 12623
4
Java也是一模一样:
Object a = 1;
System.out.println(System.identityHashCode(a)); // prints 1627674070
Object b = a;
System.out.println(System.identityHashCode(b)); // prints 1627674070
b = 5;
System.out.println(System.identityHashCode(b)); // prints 1360875712
System.out.println(a); // prints 1
Object c = 5;
System.out.println(System.identityHashCode(c)); // prints 1360875712
System.out.println(b == c); // prints true
(其实那个b == c不一定要是true。但是很巧Python和Java都缓存小的整数。如果你用
大一点的数字,好像500,Python和Java都会说false的。)
....
Object[] a = new Object[]{1};
System.out.println(System.identityHashCode(a)); // prints 1627674070
Object[] b = a;
System.out.println(System.identityHashCode(a)); // prints 1627674070
b[0] = 2;
System.out.println(Arrays.toString(b)); // prints [2]
System.out.println(Arrays.toString(a)); // prints [2]
b = new Object[]{3};
System.out.println(System.identityHashCode(b)); // prints 1360875712
System.out.println(Arrays.toString(a)); // prints [2]

NET

【在 p**z 的大作中提到】
: 首先,我同意 Python 里的 name 也叫做 variable。Python 自己文档里面就是混用的
: 。但是它的真正行为确实是一个名字,跟其他 statically typed 语言的变量有所不同
: 。另外,原帖中 by value 和 by reference 的表述并不准确,因为那是我以 VB.NET
: 的行为来打比方的,并没有严格按照这两个术语的原意。
: 我简单看了一下 Python 和 Java 的文档,觉得它们还是有很大不同的。
: 对于 Python,可以看一下它的 language reference, 3.1. Objects, values and
: types, 以及 4.1. Naming and binding。如果我理解没有错的话,Python 没有简单数
: 据类型,所有的数据都是对象。每个对象有自己的唯一的身份(不可改变),类型(不
: 可改变),内容(有些 immutable,比如整数,浮点数,字符串;有些 mutable,比如
: list,dictionary)。Python 是 dynamic typing 的,就是说一个名字(变量)使用

p**z
发帖数: 65
5
这样看来 Python 和 Java 对象变量的行为都一样。不同是 Python 没有 Java 的
primitive data types,所以所有的数据都必须是对象。
我试了一下,Python 在大整数情形下的确如你所说,相同值的两个大整数不一定是相
同的对象。浮点数也无法缓存,所以相同值的两个浮点数也不是一定是相同的对象。
>>> a = 4385948945
>>> id(a)
140450544L
>>> b = 4385948945
>>> id(b)
140450928L
>>> a is b
False
>>> a = 1.2
>>> id(a)
141991984L
>>> b = 1.2
>>> id(b)
141991960L
>>> a is b
False
"小“整数和”大“整数的边界在 Python 里好像就是一个byte:
>>> a = 256
>>> b = 256
>>> a is b
True
>>> a = 257
>>> b = 257
>>> a is b
False
关于 string 这个表现很有趣:似乎没有 white space 的 string 跟有 white space
的表现不同:
>>> a = 'thisisateststring'
>>> b = 'thisisateststring'
>>> a is b
True
>>> a = 'this is a test string'
>>> b = 'this is a test string'
>>> a is b
False
>>>
f*******n
发帖数: 12623
6
有没有primitive没有什么区别。primitive用起来跟immutable的对象的reference的效
果一样,除了primitive的==等于reference的.equals()之外。以上也可以用primitive
的整数:
int a = 1;
int b = a;
b = 5;
System.out.println(a); // prints 1
...
int[] a = new int[]{1};
int[] b = a;
b[0] = 2;
System.out.println(Arrays.toString(b)); // prints [2]
System.out.println(Arrays.toString(a)); // prints [2]
b = new int[]{3};
System.out.println(Arrays.toString(a)); // prints [2]

【在 p**z 的大作中提到】
: 这样看来 Python 和 Java 对象变量的行为都一样。不同是 Python 没有 Java 的
: primitive data types,所以所有的数据都必须是对象。
: 我试了一下,Python 在大整数情形下的确如你所说,相同值的两个大整数不一定是相
: 同的对象。浮点数也无法缓存,所以相同值的两个浮点数也不是一定是相同的对象。
: >>> a = 4385948945
: >>> id(a)
: 140450544L
: >>> b = 4385948945
: >>> id(b)
: 140450928L

p**z
发帖数: 65
7
Hmm... 那么如果在 Java 里面定义两个整形变量,
int a = 1;
int b = 1;
难道不是开辟两个整形变量的空间,分别存入1吗?
f*******n
发帖数: 12623
8
是。但是你也可以把它们当作两个Integer对象reference的变量,都指向1的Integer对
象。

【在 p**z 的大作中提到】
: Hmm... 那么如果在 Java 里面定义两个整形变量,
: int a = 1;
: int b = 1;
: 难道不是开辟两个整形变量的空间,分别存入1吗?

1 (共1页)
相关主题
Google I/O 2008 - Painless Python└ Re: python程序运行速度的问题
面试题的Python实现Is it possible to use c++ objects from python code?
sec and python└ Re: Is it possible to use c++ objects from python code?
One question about import exe result to python script├ Re: Is it possible to use c++ objects from python code?
如何用 Python 修改 mp3 文件的音乐标题└ Re: Re: Is it possible to use c++ objects from python co
初级问题:怎么指代上一个命令的输出Question about this python error.
Re: python .pyw问题请教An easter egg in Python :)
python程序运行速度的问题 (转载)精华区里新加了很多东西
相关话题的讨论汇总
话题: python话题: 对象话题: prints话题: object话题: java