流畅的Python (豆瓣)

您所在的位置:网站首页 python中的python 流畅的Python (豆瓣)

流畅的Python (豆瓣)

2022-05-31 23:22| 来源: 网络整理| 查看: 265

关于Python的数据模型

Python的内建方法系列是一种抽象,类通过实现各种dunder method,对外做出完全一致的呈现。而Python的基本语法和标准库就是呈现各种一致性操作的方式。这是这个语言整洁的地方。C++里面运算符重载,也是类似的作用。但python的抽象性更强,因为不仅覆盖了各种运算符操作,还有标准库。这是Object基类里包含的操作。这就是Python的数据模型。

//关于操作符,二元操作符 a * b,可以转化为前缀表达式 +, a, b,进而转化为

__repr__ 和 __str__ 的区别在于,后者是在 str() 函数被使用,或是在用 print 函数打印 一个对象的时候才被调用的,并且它返回的字符串对终端用户更友好。 如果你只想实现这两个特殊方法中的一个,__repr__ 是更好的选择,因为如果一个对象没 有 __str__ 函数,而 Python 又需要调用它的时候,解释器会用 __repr__ 作为替代。

Python 对象的一个基本要求就是它得有合理的字符串表示形式,我们可以通过 __repr__ 和 __str__ 来满足这个要求。前者方便我们调试和记录日志,后者则是给终端用户看的。这 就是数据模型中存在特殊方法 __repr__ 和 __str__ 的原因。

Objects are Python’s abstraction for data. All data in a Python program is represented by objects or by relations between objects. (In a sense, and in conformance to Von Neumann’s model of a “stored program computer,” code is also represented by objects.)

Every object has an identity, a type and a value. An object’s identity never changes once it has been created; you may think of it as the object’s address in memory. The ‘is’ operator compares the identity of two objects; the id() function returns an integer representing its identity.

CPython implementation detail: For CPython, id(x) is the memory address where x is stored.

元对象协议(metaobject protocol,MOP)的概念

可以用 * 运算符把一个可迭代对象拆开作为函数的参数:

>>> divmod(20, 8) (2, 4) >>> t = (20, 8) >>> divmod(*t) (2, 4) >>> quotient, remainder = divmod(*t) >>> quotient, remainder (2, 4)

用 namedtuple 构建的类的实例所消耗的内存跟元组是一样的,因为字段名都 被存在对应的类里面。这个实例跟普通的对象实例比起来也要小一些,因为 Python 不会用 __dict__ 来存放这些实例的属性。

有时候为了方便起见,就算某个键在映射里不存在,我们也希望在通过这个键读取值的 时候能得到一个默认值。有两个途径能帮我们达到这个目的,一个是通过 defaultdict 这 个类型而不是普通的 dict,另一个是给自己定义一个 dict 的子类,然后在子类中实现 __missing__ 方法。

然而,Python 简单的句法限制了 lambda 函数的定义体只能使用纯表达式。换句话说, lambda 函数的定义体中不能赋值,也不能使用 while 和 try 等 Python 语句。

装饰器的一个关键特性是,它们在被装饰的函数定义之后立即运行。这通常是在导入时

(即 Python 加载模块时)

Python 3 引入了 nonlocal 声明。它的作用是把变量标记为自由变量, 即使在函数中为变量赋予新值了,也会变成自由变量

del 语句删除名称,而不是对象。del 命令可能会导致对象被当作垃圾回收,但是仅当删除 的变量保存的是对象的最后一个引用,或者无法得到对象时。2 重新绑定也可能会导致对象 的引用数量归零,导致对象被销毁。

弱引用不会增加对象的引用数量。引用的目标对象称为所指对象(referent)。因此我们说, 弱引用不会妨碍所指对象被当作垃圾回收。

弱引用在缓存应用中很有用,因为我们不想仅因为被缓存引用着而始终保存缓存对象。

不是每个 Python 对象都可以作为弱引用的目标(或称所指对象)。基本的 list 和 dict 实例不能作为所指对象,但是它们的子类可以轻松地解决这个问题 set 实例可以作为所指对象。用户定义的类型也没问题。但是,int 和 tuple 实例不能作 为弱引用的目标,甚至它们的子类也不行。

每个 Python 对象都有标识、类型和值。只有对象的值会不时变化。

如果两个变量指代的不可变对象具有相同的值(a == b为True),实际上它们指代的是副 本还是同一个对象的别名基本没什么关系,因为不可变对象的值不会变,但有一个例外。 这里说的例外是不可变的集合,如元组和 frozenset:如果不可变集合保存的是可变元素 的引用,那么可变元素的值发生变化后,不可变集合也会随之改变。实际上,这种情况不 是很常见。不可变集合不变的是所含对象的标识。

变量保存的是引用,这一点对 Python 编程有很多实际的影响。

简单的赋值不创建副本。 对 += 或 *= 所做的增量赋值来说,如果左边的变量绑定的是不可变对象,会创建新对象; 如果是可变对象,会就地修改。 为现有的变量赋予新值,不会修改之前绑定的变量。这叫重新绑定:现在变量绑定了其 他对象。如果变量是之前那个对象的最后一个引用,对象会被当作垃圾回收。 函数的参数以别名的形式传递,这意味着,函数可能会修改通过参数传入的可变对象。 这一行为无法避免,除非在本地创建副本,或者使用不可变对象(例如,传入元组,而 不传入列表)。 使用可变类型作为函数参数的默认值有危险,因为如果就地修改了参数,默认值也就变 了,这会影响以后使用默认值的调用。

推荐 回应   2018-03-08 11:26:59


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3