Python进阶 - 对象,名字以及绑定 写在前面 如非特别说明,下文均基于 Python3
1、一切皆对象 Python 哲学:
Python中一切皆对象
1.1 数据模型-对象,值以及类型 对象是 Python 对数据的抽象。 Python 程序中所有的数据都是对象或对象之间的关系表示的。(在某种意义上,为顺应冯·诺依曼“存储式计算机”的模型, Python 中的代码也是对象。)
Python 中每一个对象都有一个身份标识,一个值以及一个类型。对象创建后,其身份标识绝对不会改变;可以把身份标识当做对象在内存中的地址。 is 操作符比较两个对象的身份标识; id() 函数返回表示对象身份标识的整数。
CPython实现细节: 在 CPython 解释器的实现中, id(x) 函数返回存储 x 的内存地址
对象的类型决定了对象支持的操作(例如,对象有长度么?),同时也决定了该类型对象可能的值。 type() 函数返回对象的类型(这个类型本身也是一个对象)。与其身份标识一样,对象的类型也是不可改变的 [1] 。
一些对象的值可以改变。可改变值的对象也称作 可变的(mutable) ;一旦创建,值恒定的对象也叫做 不可变的(immutable) 。(当不可变容器对象中包含对可变对象的引用时,可变对象值改变时,这个不可变容器对象值也被改变了;然而,不可变容器对象仍被认为是不可变的,因为对象包含的值集合确实是不可改变的。因此,不可变性不是严格等同于拥有不可变的值,它很微妙。) (译注:首先不可变容器对象的值是一个集合,集合中包含了对其他对象的引用;那么这些引用可以看做地址,即使地址指向的内容改变了,集合中的地址本身是没有改变的。所以不可变容器对象还是不可变对象。) 对象的可变性取决于其类型;例如,数字,字符串和元组是不可变的,但字典和列表是可变的。
对象从不显式销毁;当对象不可达时会被垃圾回收(译注:对象没有引用了)。一种解释器实现允许垃圾回收延时或者直接忽略——这取决于垃圾回收是如何实现的,只要没有可达对象被回收。
CPython实现细节: CPython 解释器实现使用引用计数模式延时探测循环链接垃圾,这种方式可回收大多数不可达对象,但并不能保证循环引用的垃圾被回收。查看 gc 模块的文档了解控制循环垃圾回收的更多信息。其他解释器实现与 CPython 不同, CPython 实现将来也许会改变。因此不能依赖垃圾回收器来回收不可达对象(因此应该总是显式关闭文件对象。)。
需要注意,使用工具的调试跟踪功能可能会导致应该被回收的对象一直存活,使用 try ... except 语句捕获异常也可以保持对象的存活。
一些对象引用了如文件或者窗口的外部资源。不言而喻持有资源的对象被垃圾回收后,资源也会被释放,但因为没有机制保证垃圾回收一定会发生,这些资源持有对象也提供了显式释放外部资源的方式,通常使用 close() 方法。强烈推荐在程序中显式释放资源。 try ... finally 语句和 with 语句为释放资源提供了便利。
一些对象包含对其他对象的引用,这些对象被称作 容器 。元组,列表和字典都是容器。引用的容器值的一部分。大多数情况下,谈论容器的值时,我们暗指容器包含的对象值集合,而不是对象的身份标识集合;然而,谈论容器的可变性时,我们暗指容器包含的对象的身份标识。因此,如果不可变对象(如元组)包含对可变对象的引用,可变对象改变时,其值也改变了。
类型影响对象的绝大多数行为。在某些情况下甚至对象的身份标识的重要性也受到影响:对于不可变类型,计算新值的操作实际上可能会返回已存在的,值和类型一样的对象的引用,然而对于可变对象来说这是不可能的。例如,语句 a = 1; b = 1 执行之后, a 和 b 可能会也可能不会引用具有相同值得同一个对象,这取决于解释器实现。但是语句 c = []; d = [] 执行之后,可以保证 c 和 d 会指向不同的,唯一的新创建的空列表。(注意 c = d = [] 分配相同的对象给 c 和 d )
Note: 以上翻译自 《The Python Language References#Data model# Objects, values, types》 3.6.1版本。
1.2 对象小结 官方文档已经对 Python 对象做了详细的描述,这里总结一下。
对象的三个特性:
身份标识
唯一标识对象;不可变; CPython 解释器实现为对象的内存地址。
操作: id() ,内建函数 id() 函数返回标识对象的一个整数; is 比较两个对象的身份标识。
示例:
>>> id(1)
1470514832
>>> 1 is 1
True
类型
决定对象支持的操作,可能的值;不可变。
操作: type() ,内建函数返回对象的类型
示例:
>>> type('a')
<class 'str'>
值
数据,可变/不可变
操作: == 操作符用于比较两个对象的值是否相等,其他比较运算符比较对象间大小情况。
示例:
>>> 'python'
'python'
>>> 1 == 2
False
# -*- coding: utf-8 -*-# filename: hello.py'a test module'author = 'Richard Cheng'import sysclass Person(object): ''' Person class'''
def init(self, name, age): self.name = name self.age = agedef tset(): print(sys.path)
p = Person('Richard', 20) print(p.name, ':', p.age)def main():
tset()if name == 'main':
main()
public static void main(String[] args) { int i = 0; // 先声明,后使用
System.out.println(i); // 使用变量i}
3.4 引用可变对象 3.4.1 示例1:改变可变对象的值 >>> list1 = [1]>>> id(list1)42695136>>> list1.append(2)>>> id(list1)42695136>>> list1
[1, 2]>>>
values = [1, 2, 3]
values[1] = valuesprint(values)
def attempt_change_immutable(i):
i = 2i = 1print(i)
attempt_change_immutable(i)print(i)
def attempt_change_mutable(list_param):
list_param.append('test')
list1 = [1]print(list1)
attempt_change_mutable(list1)print(list1)
[1]
[1, 'test']
可以看到函数成功改变了列表 list1 的值。传递参数时,名字 list_param 引用了与名字 list1 相同的对象,这个对象是可变的,在函数中成功修改了对象的值。
首先,名字 list_param 与名字 list1 指向对象:
然后,通过名字 list_param 修改了对象的值:
最后,这个修改对名字 list1 可见。
3.6 绑定何时发生 总的来说,触发名字对象绑定的行为有以下一些:
赋值操作; a = 1
函数定义;
def test():
pass
将名字 test 绑定到函数对象
类定义:
class Test(object):
pass
将名字 Test 绑定到类对象
函数传参;
def test(i):
pass
test(1)
将名字 i 绑定到整数对象 1
import 语句:
import sys
将名字 sys 绑定到指定模块对象。
for 循环
for i in range(10):
pass
每次循环都会绑定/重绑定名字 i
as 操作符
with open('dir', 'r') as f:
pass
try:
pass
except NameError as ne:
pass
with open 语句,异常捕获语句中的 as 都会发生名字的绑定
4、其他说明 待续。。。
参考 The Python Language References#Data model# Objects, values, types
Python的名字绑定
Python一切皆对象
Code Like a Pythonista: Idiomatic Python
python基础(5):深入理解 python 中的赋值、引用、拷贝、作用域
脚注 [1] 在特定的控制条件下,改变对象的类型是可能的。但不是一种明智的做法,如果处理不当的话,会发生一些奇怪的行为。
以上就是Python对象,名字以及绑定的详细内容,更多请关注Gxl网其它相关文章!
声明:本文来自网络,不代表【好得很程序员自学网】立场,转载请注明出处:http://www.haodehen.cn/did82309
如非特别说明,下文均基于 Python3
1、一切皆对象Python 哲学:
Python中一切皆对象
1.1 数据模型-对象,值以及类型对象是 Python 对数据的抽象。 Python 程序中所有的数据都是对象或对象之间的关系表示的。(在某种意义上,为顺应冯·诺依曼“存储式计算机”的模型, Python 中的代码也是对象。)
Python 中每一个对象都有一个身份标识,一个值以及一个类型。对象创建后,其身份标识绝对不会改变;可以把身份标识当做对象在内存中的地址。 is 操作符比较两个对象的身份标识; id() 函数返回表示对象身份标识的整数。
CPython实现细节: 在 CPython 解释器的实现中, id(x) 函数返回存储 x 的内存地址
对象的类型决定了对象支持的操作(例如,对象有长度么?),同时也决定了该类型对象可能的值。 type() 函数返回对象的类型(这个类型本身也是一个对象)。与其身份标识一样,对象的类型也是不可改变的 [1] 。
一些对象的值可以改变。可改变值的对象也称作 可变的(mutable) ;一旦创建,值恒定的对象也叫做 不可变的(immutable) 。(当不可变容器对象中包含对可变对象的引用时,可变对象值改变时,这个不可变容器对象值也被改变了;然而,不可变容器对象仍被认为是不可变的,因为对象包含的值集合确实是不可改变的。因此,不可变性不是严格等同于拥有不可变的值,它很微妙。) (译注:首先不可变容器对象的值是一个集合,集合中包含了对其他对象的引用;那么这些引用可以看做地址,即使地址指向的内容改变了,集合中的地址本身是没有改变的。所以不可变容器对象还是不可变对象。) 对象的可变性取决于其类型;例如,数字,字符串和元组是不可变的,但字典和列表是可变的。
对象从不显式销毁;当对象不可达时会被垃圾回收(译注:对象没有引用了)。一种解释器实现允许垃圾回收延时或者直接忽略——这取决于垃圾回收是如何实现的,只要没有可达对象被回收。
CPython实现细节: CPython 解释器实现使用引用计数模式延时探测循环链接垃圾,这种方式可回收大多数不可达对象,但并不能保证循环引用的垃圾被回收。查看 gc 模块的文档了解控制循环垃圾回收的更多信息。其他解释器实现与 CPython 不同, CPython 实现将来也许会改变。因此不能依赖垃圾回收器来回收不可达对象(因此应该总是显式关闭文件对象。)。
需要注意,使用工具的调试跟踪功能可能会导致应该被回收的对象一直存活,使用 try ... except 语句捕获异常也可以保持对象的存活。
一些对象引用了如文件或者窗口的外部资源。不言而喻持有资源的对象被垃圾回收后,资源也会被释放,但因为没有机制保证垃圾回收一定会发生,这些资源持有对象也提供了显式释放外部资源的方式,通常使用 close() 方法。强烈推荐在程序中显式释放资源。 try ... finally 语句和 with 语句为释放资源提供了便利。
一些对象包含对其他对象的引用,这些对象被称作 容器 。元组,列表和字典都是容器。引用的容器值的一部分。大多数情况下,谈论容器的值时,我们暗指容器包含的对象值集合,而不是对象的身份标识集合;然而,谈论容器的可变性时,我们暗指容器包含的对象的身份标识。因此,如果不可变对象(如元组)包含对可变对象的引用,可变对象改变时,其值也改变了。
类型影响对象的绝大多数行为。在某些情况下甚至对象的身份标识的重要性也受到影响:对于不可变类型,计算新值的操作实际上可能会返回已存在的,值和类型一样的对象的引用,然而对于可变对象来说这是不可能的。例如,语句 a = 1; b = 1 执行之后, a 和 b 可能会也可能不会引用具有相同值得同一个对象,这取决于解释器实现。但是语句 c = []; d = [] 执行之后,可以保证 c 和 d 会指向不同的,唯一的新创建的空列表。(注意 c = d = [] 分配相同的对象给 c 和 d )
Note: 以上翻译自 《The Python Language References#Data model# Objects, values, types》 3.6.1版本。
1.2 对象小结官方文档已经对 Python 对象做了详细的描述,这里总结一下。
对象的三个特性:
身份标识
唯一标识对象;不可变; CPython 解释器实现为对象的内存地址。
操作: id() ,内建函数 id() 函数返回标识对象的一个整数; is 比较两个对象的身份标识。
示例:>>> id(1) 1470514832 >>> 1 is 1 True类型
决定对象支持的操作,可能的值;不可变。
操作: type() ,内建函数返回对象的类型
示例:>>> type('a') <class 'str'>值
数据,可变/不可变
操作: == 操作符用于比较两个对象的值是否相等,其他比较运算符比较对象间大小情况。
示例:>>> 'python' 'python' >>> 1 == 2 False# -*- coding: utf-8 -*-# filename: hello.py'a test module'author = 'Richard Cheng'import sysclass Person(object): ''' Person class''' def init(self, name, age): self.name = name self.age = agedef tset(): print(sys.path) p = Person('Richard', 20) print(p.name, ':', p.age)def main(): tset()if name == 'main': main()public static void main(String[] args) { int i = 0; // 先声明,后使用 System.out.println(i); // 使用变量i}3.4 引用可变对象 3.4.1 示例1:改变可变对象的值>>> list1 = [1]>>> id(list1)42695136>>> list1.append(2)>>> id(list1)42695136>>> list1 [1, 2]>>>values = [1, 2, 3] values[1] = valuesprint(values)def attempt_change_immutable(i): i = 2i = 1print(i) attempt_change_immutable(i)print(i)def attempt_change_mutable(list_param): list_param.append('test') list1 = [1]print(list1) attempt_change_mutable(list1)print(list1)[1] [1, 'test']可以看到函数成功改变了列表 list1 的值。传递参数时,名字 list_param 引用了与名字 list1 相同的对象,这个对象是可变的,在函数中成功修改了对象的值。
首先,名字 list_param 与名字 list1 指向对象:
然后,通过名字 list_param 修改了对象的值:
最后,这个修改对名字 list1 可见。
3.6 绑定何时发生总的来说,触发名字对象绑定的行为有以下一些:
赋值操作; a = 1
函数定义;
def test(): pass将名字 test 绑定到函数对象
类定义:
class Test(object): pass将名字 Test 绑定到类对象
函数传参;
def test(i): pass test(1)将名字 i 绑定到整数对象 1
import 语句:
import sys将名字 sys 绑定到指定模块对象。
for 循环
for i in range(10): pass每次循环都会绑定/重绑定名字 i
as 操作符
with open('dir', 'r') as f: pass try: pass except NameError as ne: passwith open 语句,异常捕获语句中的 as 都会发生名字的绑定
4、其他说明待续。。。
参考The Python Language References#Data model# Objects, values, types
Python的名字绑定
Python一切皆对象
Code Like a Pythonista: Idiomatic Python
python基础(5):深入理解 python 中的赋值、引用、拷贝、作用域
脚注[1] 在特定的控制条件下,改变对象的类型是可能的。但不是一种明智的做法,如果处理不当的话,会发生一些奇怪的行为。
以上就是Python对象,名字以及绑定的详细内容,更多请关注Gxl网其它相关文章!
声明:本文来自网络,不代表【好得很程序员自学网】立场,转载请注明出处:http://www.haodehen.cn/did82309