별도의 언급이 없는 한 다음은
Python3
Python3
Python
哲学:
Python中一切皆对象
对象是Python
对数据的抽象。Python
程序中所有的数据都是对象或对象之间的关系表示的。(在某种意义上,为顺应冯·诺依曼“存储式计算机”的模型,Python
中的代码也是对象。)
Python
中每一个对象都有一个身份标识,一个值以及一个类型。对象创建后,其身份标识绝对不会改变;可以把身份标识当做对象在内存中的地址。is
操作符比较两个对象的身份标识;id()
函数返回表示对象身份标识的整数。
CPython实现细节: 在CPython
解释器的实现中,id(x)
函数返回存储x
的内存地址
对象的类型决定了对象支持的操作(例如,对象有长度么?),同时也决定了该类型对象可能的值。type()
函数返回对象的类型(这个类型本身也是一个对象)。与其身份标识一样,对象的类型也是不可改变的[1]。
一些对象的值可以改变。可改变值的对象也称作可变的(mutable);一旦创建,值恒定的对象也叫做 不可变的(immutable)。(当不可变容器对象中包含对可变对象的引用时,可变对象值改变时,这个不可变容器对象值也被改变了;然而,不可变容器对象仍被认为是不可变的,因为对象包含的值集合确实是不可改变的。因此,不可变性不是严格等同于拥有不可变的值,它很微妙。) (译注:首先不可变容器对象的值是一个集合,集合中包含了对其他对象的引用;那么这些引用可以看做地址,即使地址指向的内容改变了,集合中的地址本身是没有改变的。所以不可变容器对象还是不可变对象。) 对象的可变性取决于其类型;例如,数字,字符串和元组是不可变的,但字典和列表是可变的。
对象从不显式销毁;当对象不可达时会被垃圾回收(译注:对象没有引用了)。一种解释器实现允许垃圾回收延时或者直接忽略——这取决于垃圾回收是如何实现的,只要没有可达对象被回收。
CPython实现细节: CPython
解释器实现使用引用计数模式延时探测循环链接垃圾,这种方式可回收大多数不可达对象,但并不能保证Python 객체, 이름 및 바인딩的垃圾被回收。查看gc
模块的文档了解控制循环垃圾回收的更多信息。其他解释器实现与CPython
不同,CPython
实现将来也许会改变。因此不能依赖垃圾回收器来回收不可达对象(因此应该总是显式关闭文件对象。)。
需要注意,使用工具的调试跟踪功能可能会导致应该被回收的对象一直存活,使用try
...
except
语句捕获异常也可以保持对象的存活。
一些对象引用了如文件或者窗口的外部资源。不言而喻持有资源的对象被垃圾回收后,资源也会被释放,但因为没有机制保证垃圾回收一定会发生,这些资源持有对象也提供了显式释放外部资源的方式,通常使用close()
方法。强烈推荐在程序中显式释放资源。try
...
<a href="http://www.php.cn/wiki/207.html" target="_blank">final</a>ly
语句和with
Python
철학: 🎜🎜🎜Python의 모든 것은 객체입니다🎜Python
의 데이터 추상화입니다. Python
프로그램의 모든 데이터는 개체 또는 개체 간의 관계로 표현됩니다. (어떤 의미에서는 von Neumann의 "저장 컴퓨터" 모델을 따르기 위해 Python
의 코드도 객체입니다.)🎜🎜Python
객체의 모든 것에는 ID, 값 및 유형. 객체가 생성된 후에는 그 ID가 결코 변경되지 않습니다. ID는 메모리에 있는 객체의 주소로 생각할 수 있습니다. is
Operator 🎜는 두 객체의 ID를 비교합니다. id ()
Function🎜반환 정수 🎜. 🎜🎜CPython 구현 세부 정보: CPython
인터프리터 구현에서 id(x)
함수는 저장된 x를 반환합니다. code> 객체의 메모리 주소는 객체가 지원하는 작업(예: 객체에 길이가 있습니까?)을 결정하고 이 유형의 객체에 가능한 값도 결정합니다. <code>type()
함수는 객체의 유형을 반환합니다(이 유형 자체도 객체입니다). ID와 마찬가지로 객체 유형도 변경할 수 없습니다[1]. 🎜🎜일부 개체의 값은 변경될 수 있습니다. 값이 변경될 수 있는 개체는 변경 가능이라고도 하며, 생성된 후 값이 일정한 개체는 불변(immutable)이라고도 합니다. em>. (불변 컨테이너 객체가 가변 객체에 대한 참조를 포함하는 경우, 가변 객체의 값이 변경되면 불변 컨테이너 객체 값도 변경됩니다. 그러나 불변 컨테이너 객체는 포함된 값 모음 때문에 여전히 불변으로 간주됩니다. 따라서 불변성은 불변성과 엄격하게 동일하지 않습니다. 값은 매우 미묘합니다. ) (주석: 우선 불변 컨테이너 객체의 값은 다른 객체에 대한 참조를 포함합니다. 그러면 이러한 참조는 주소로 간주될 수 있습니다. 주소가 가리키는 내용이 변경되더라도 주소 자체는 변경되지 않습니다. 예를 들어 개체의 변경 가능성은 다음과 같습니다. 숫자, 문자열과 튜플은 변경할 수 없지만 사전과 목록은 변경할 수 있습니다. 🎜🎜객체는 명시적으로 삭제되지 않습니다. 객체에 접근할 수 없으면 가비지 수집됩니다(주석: 객체에 참조가 없습니다). 하나의 인터프리터 구현을 사용하면 가비지 수집을 지연하거나 완전히 무시할 수 있습니다. 이는 도달 가능한 객체가 수집되지 않는 한 가비지 수집 구현 방법에 따라 다릅니다. 🎜🎜CPython 구현 세부 정보: CPython
인터프리터는 참조 계산 모드 순환 🎜 링크 쓰레기, 이 방법은 도달할 수 없는 대부분의 객체를 재활용할 수 있지만 순환 참조의 쓰레기가 재활용된다는 보장은 없습니다. 순환 가비지 수집 제어에 대한 자세한 내용은 gc
모듈 설명서를 참조하세요. 다른 인터프리터 구현은 CPython
과 다르며 CPython
구현은 향후 변경될 수 있습니다. 따라서 가비지 수집기는 연결할 수 없는 개체를 회수하는 데 의존할 수 없습니다(따라서 파일 개체는 항상 명시적으로 닫혀야 합니다). 🎜🎜도구의 디버깅🎜추적 기능을 사용하면 재활용해야 할 개체가 남을 수 있다는 점에 유의하세요. 예외를 포착하기 위해 try
...
out
문을 사용하면 객체를 활성 상태로 유지할 수도 있습니다. 🎜🎜일부 개체는 파일이나 창과 같은 외부 리소스를 참조합니다. 리소스를 보유하고 있는 개체가 가비지 수집된 후에 리소스도 해제된다는 것은 말할 필요도 없습니다. 그러나 가비지 수집이 반드시 발생한다는 것을 보장하는 메커니즘이 없기 때문에 이러한 리소스 보유 개체는 외부에서 명시적으로 해제하는 방법도 제공합니다. 일반적으로 close() 메서드를 사용합니다. 프로그램에서 리소스를 명시적으로 해제하는 것이 좋습니다. 시도
...
<a href="http://www.php.cn/wiki/207.html" target="_blank">최종🎜 ly</a>
문과 with
문은 리소스 해제에 대한 편의를 제공합니다. 🎜일부 개체에는 다른 개체에 대한 참조가 포함되어 있으며 이러한 개체를 컨테이너라고 합니다. 튜플, 리스트, 딕셔너리는 모두 컨테이너입니다. 참조된 컨테이너 값의 일부입니다. 대부분의 경우 컨테이너의 값에 대해 이야기할 때는 객체의 ID 집합이 아닌 컨테이너에 포함된 객체 값 집합을 언급합니다. 우리는 그것이 포함하는 객체의 정체성을 암시하고 있습니다. 따라서 불변 객체(예: 튜플)에 가변 객체에 대한 참조가 포함되어 있는 경우 가변 객체가 변경되면 해당 값도 변경됩니다.
유형은 개체의 대부분의 동작에 영향을 미칩니다. 어떤 경우에는 객체 ID의 중요성조차 영향을 받습니다. 불변 유형의 경우 새 값을 계산하는 작업은 실제로 동일한 값과 유형을 가진 기존 객체에 대한 참조를 반환할 수 있지만, 가변 객체의 경우 이는 불가능합니다. 예를 들어 a = 1; b = 1
문이 실행된 후 a
와 b
는 다음과 같은 개체를 참조할 수도 있고 참조하지 않을 수도 있습니다. 동일한 값입니다. 이는 인터프리터 구현에 따라 다릅니다. 그러나 c = []; d = []
문이 실행된 후에는 c
와 d
가 서로 다른 위치를 가리킬 것이 보장됩니다. 새로 생성된 고유한 빈 목록입니다. (c = d = []
는 동일한 객체를 c
및 d
에 할당합니다.)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版本。
官方文档已经对Python
对象做了详细的描述,这里总结一下。
对象的三个特性:
身份标识
唯一标识对象;不可变;CPython
解释器实现为对象的内存地址。
操作:id()
,内建函数id()
函数返回标识对象的一个整数;is
比较两个对象的身份标识。
示例:
>>> id(1) 1470514832 >>> 1 is 1 True
类型
决定对象支持的操作,可能的值;不可变。
操作:type()
,内建函数返回对象的类型
示例:
>>> type('a') <class></class>
值
数据,可变/不可变
操作:==
操作符用于比较两个对象的值是否相等,其他比较运算符比较对象间大小情况。
示例:
>>> 'python' 'python' >>> 1 == 2 False
可变与不可变:一般认为,值不可变的对象是不可变对象,值可变的对象是可变对象,但是要注意不可变集合对象包含可变对象引用成员的情况。
Python
中的对象:
# -*- 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()
这段Python
代码中有很多对象,包括hello
这个模块对象,创建的Person
类对象,几个函数如test
, main
函数对象,数字,字符串,甚至代码本身也是对象。
几乎所有语言中都有“变量”的说法,严格说来,Python
中的变量不应该叫变量,称为名字更加贴切。
以下翻译自 Code Like a Pythonista: Idiomatic Python # Python has "names"
其他语言中,为变量分配值就像将值放到“盒子”里。int a = 1;
盒子a
现在有了一个整数1
。
为同一个变量分配值替换掉盒子的内容:a =2;
现在盒子a
中放了整数2
将一个变量分配给另一个变量,拷贝变量的值,并把它放到新的盒子里:int b = a;
b
是第二个盒子,装有整数2的拷贝。盒子a
有一份单独的拷贝。
Python
中,名字或者标识符就像将一个标签捆绑到对象上一样。a = 1
참고: 위의 내용은 다음에서 번역되었습니다. "Python" Lang
uage References#Data 모델🎜# 객체🎜 s, 값, 유형》버전 3.6.1. 🎜Python
개체에 대한 자세한 설명이 나와 있습니다. 🎜🎜🎜객체의 세 가지 특성: 🎜🎜id()
, 내장 함수 id()
함수는 is
비교를 식별하는 정수를 반환합니다. 두 가지 정체성의 대상. public static void main(String[] args) { int i = 0; // 先声明,后使用 System.out.println(i); // 使用变量i}
type()
, 내장 함수는 객체의 유형을 반환합니다.a = 9
==
연산자는 두 개체의 값이 같은지 비교하는 데 사용됩니다. 기타비교 연산자 🎜객체의 크기를 비교합니다. a = 9 #1a = a + 1 #2
Python
의 개체: 🎜🎜
🎜
>>> a = 9>>> id(a)1470514960>>> a = a + 1>>> id(a)1470514976🎜
Python
코드에는 다음이 있습니다. 모듈 개체 hello
, 생성된 Person
클래스 개체 및 test
, main
와 같은 여러 함수를 포함한 많은 개체 > >함수 객체, 숫자, 문자열, 심지어 코드 자체도 객체입니다. 🎜
Python
의 변수는 변수라고 부르면 안 됩니다. 🎜🎜다음 번역은 Code Like a Pythonista에서 가져온 것입니다: Idiomatic Python # Python has "names"🎜int a = 1;
🎜🎜🎜🎜a
상자에는 이제 정수 1
이 있습니다. 🎜🎜같은 변수에 값을 할당하고 상자의 내용을 바꿉니다:a =2;
🎜🎜🎜🎜이제 정수 2
가 상자 a 🎜🎜한 변수를 다른 변수에 할당하고 변수 값을 복사한 다음 새 상자에 넣으세요.<br><code>int b = a;
🎜🎜🎜🎜🎜🎜b
는 두 번째 상자입니다. 복사본이 있습니다. 정수 2의 상자 a
에는 별도의 사본이 있습니다. 🎜Python
에서 이름이나 식별자는 개체에 레이블을 바인딩하는 것과 같습니다. a = 1
🎜🎜🎜🎜这里,整数对象1
有一个叫做a
的标签。
如果重新给a
分配值,只是简单的将标签移动到另一个对象:a = 2
现在名字a
贴到了整数对象2
上面。原来的整数对象1不再拥有标签a
,或许它还存在,但是不能通过标签a
访问它了(当对象没有任何引用时,会被回收。)
如果将一个名字分配给另一名字,只是将另一个名字标签捆绑到存在的对象上:b = a
名字b
只是绑定到与a
引用的相同对象上的第二个标签而已。
虽然在Python
中普遍使用“变量”(因为“变量”是普遍术语),真正的意思是名字或者标识符。Python
中的变量是值得标签,不是装值得盒子。
C/C++
中有指针,Java
中有引用,Python
中的名字在一定程度上等同于指针和引用。
2.1节中其他语言的例子,也只是针对于它们的基本类型而言的,若是指针或者引用,表现也跟Python
的名字一样。这也在一定程度上说明了Python
将面向对象贯彻得更加彻底。
可以对一个变量做什么?声明变量,使用变量,修改变量的值。名字作为Python
中的一个重要概念,可以对它做的操作有:
定义;名字需要先定义才能使用,与变量需要先声明一样。
绑定:名字的单独存在没有意义,必须将它绑定到一个对象上。
Python 객체, 이름 및 바인딩:名字可以重新引用另一个对象,这个操作就是Python 객체, 이름 및 바인딩。
引用:为什么要定义名字,目的是使用它。
名字以及对象,它们之间必然会发生些什么。
其他如C/C++
和Java
的高级语言,变量在使用前需要声明,或者说定义。以下在Java
中声明变量:
public static void main(String[] args) { int i = 0; // 先声明,后使用 System.out.println(i); // 使用变量i}
这样,在可以访问到变量i
所在作用域的地方,既可以使用i
了。还有其他声明变量的方法么?好像没有了。
Python
中有多种定义名字的途径,如函数定义,函数名就是引用函数对象的名字;类定义,类名就是指向类对象的名字,模块定义,模块名就是引用模块对象的名字;当然,最直观的还是赋值语句。
赋值语句
官方对赋值语句做了这样的说明(地址):
Assignment statements are used to (re)bind names to values and to modify attributes or items of mutable objects.
即:
赋值语句被用来将名字绑定或者Python 객체, 이름 및 바인딩给值,也用来修改可变对象的属性或项
那么,我们关心的,就是赋值语句将名字和值(对象)绑定起来了。
看一个简单的赋值语句:
a = 9
Python
在处理这条语句时:
首先在内存中创建一个对象,表示整数9
:
然后创建名字a
,并把它指向上述对象:
上述过程就是通过赋值语句的名字对象绑定了。名字首次和对象绑定后,这个名字就定义在当前命名空间了,以后,在能访问到这个命名空间的作用域中可以引用该名字了。
定义完名字之后,就可以使用名字了,名字的使用称为“引用名字”。当名字指向可变对象和不可变对象时,使用名字会有不同的表现。
a = 9 #1a = a + 1 #2
语句1执行完后,名字a
指向表示整数9
的对象:
由于整数是不可变对象,所以在语句2处引用名字a
,试图将表示整数9
的对象 + 1
,但该对象的值是无法改变的。因此就将该对象表示的整数值9
加1
,以整数10
新建一个整数对象:
接下来,将名字a
Python 객체, 이름 및 바인딩
到新建对象上,并移除名字对原对象的引用:
使用id()
函数,可以看到名字a
指向的对象地址确实发生了改变:
>>> a = 9>>> id(a)1470514960>>> a = a + 1>>> id(a)1470514976
可变对象可以改变其值,并且不会造成地址的改变:
>>> list1 = [1]>>> id(list1)42695136>>> list1.append(2)>>> id(list1)42695136>>> list1 [1, 2]>>>
执行语句list1 = [1]
,创建一个list
对象,并且其值集中添加1
,将名字list1
指向该对象:
执行语句list1.append(2)
,由于list
是可变对象,可以直接在其值集中添加2
:
值得改变并没有造成list1
引用的对象地址的改变。
再来看一个比较“奇怪”的例子:
values = [1, 2, 3] values[1] = valuesprint(values)
一眼望去,期待的结果应该是
[1, [1, 2, 3], 3]
但实际上结果是:
[1, [...], 3]
我们知道list
中的元素可以是各种类型的,list
类型是可以的:
观察以下代码段:
>>> list1 = [1]>>> id(list1)42695136>>> list1 = [1, 2]>>> id(list1)42717432
两次输出的名字list1
引用对象的地址不一样,这是因为第二次语句list 1 = [1, 2]
对名字做了Python 객체, 이름 및 바인딩:
当两个或两个以上的名字引用同一个对象时,我们称这些名字共享对象。共享的对象可变性不同时,表现会出现差异。
函数attempt_change_immutable
将参数i
的值修改为2
def attempt_change_immutable(i): i = 2i = 1print(i) attempt_change_immutable(i)print(i)
Output:
11
如果你对输出不感到意外,说明不是新手了 ^_^。
首先,函数的参数i
与全局名字i
不是在同一命名空间中,所以它们之间不相互影响。
调用函数时,将两个名字i
都指向了同一个整数对象。
函数中修改i
的值为2
, 因为整数对象不可变,所以新建值为2
的整数对象,并把函数中的名字i
绑定到对象上。
全局名字i
的绑定关系并没有被改变。
值得注意的是,这部分内容与命名空间和作用域有关系,另外有文章介绍它们,可以参考。
函数attempt_change_mutable
为列表增加字符串。
def attempt_change_mutable(list_param): list_param.append('test') list1 = [1]print(list1) attempt_change_mutable(list1)print(list1)
output:
[1] [1, 'test']
可以看到函数成功改变了列表list1
的值。传递参数时,名字list_param
引用了与名字list1
相同的对象,这个对象是可变的,在函数中成功修改了对象的值。
首先,名字list_param
与名字list1
指向对象:
然后,通过名字list_param
修改了对象的值:
最后,这个修改对名字list1
可见。
总的来说,触发名字对象绑定的行为有以下一些:
赋值操作;a = 1
函数定义;
def test(): pass
将名字test
绑定到函数对象
类定义:
class Test(object): pass
将名字Test
绑定到类对象
函数传参;
def test(i): pass test(1)
将名字i
绑定到整数对象1
import
语句:
import sys
将名字sys
绑定到指定模块对象。
<a href="http://www.php.cn/wiki/125.html" target="_blank">for</a>
循环
for i in range(10): pass
每次循环都会绑定/Python 객체, 이름 및 바인딩名字i
as
操作符
with open('dir', 'r') as f: pass try: pass except NameError as ne: pass
with open
语句,异常捕获语句中的as
都会发生名字的绑定
待续。。。
The Python Language References#Data model# Objects, values, types
Python的名字绑定
Python一切皆对象
Code Like a Pythonista: Idiomatic Python
python基础(5):深入理解 python 中的赋值、引用、拷贝、作用域
[1] 在特定的控制条件下,改变对象的类型是可能的。但不是一种明智的做法,如果处理不当的话,会发生一些奇怪的行为。
위 내용은 Python 객체, 이름 및 바인딩의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!