流畅的Python (豆瓣) |
您所在的位置:网站首页 › python中的python › 流畅的Python (豆瓣) |
关于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 |