首页 > 编程语言 >流畅的python--第五章/第六章

流畅的python--第五章/第六章

时间:2024-05-28 17:46:04浏览次数:27  
标签:passengers 示例 python self 元组 -- 对象 引用 第六章

数据类构建器

一个简单的类,表示地理位置的经纬度。
使用nametuple构建Coordinate类。namedtuple是一个工厂方法,使用指定的名称和字段构建tuple的子类。

典型的具名元组

collections.namedtuple是一个工厂函数,用于构建增强的tuple子类,具有字段名称、类名和提供有用的信息的__repr__方法。
namedtuple构建的类可在任何需要元组的地方使用。
示例1:定义一个具名元组,存储一个城市的信息

除了从tuple继承,具名元组还有几个额外的属性和方法。

示例2:构建一个具名元组,为字段指定默认值

@dataclass 示例:都柏林核心模式

实际使用中通常需要更多的字段。根据都柏林核心(Dublin Core)模式,使用 @dataclass 构建一个
更复杂的类。都柏林核心模式是一小组术语,可用于描述数字资源(视频、图
像、网页等),也可用于描述物理资源,例如图书、CD 和艺术品
等对象。

关键字模式

import typing
class City(typing.NamedTuple):
    continent: str
    name: str
    country: str
cities = [
City('Asia', 'Tokyo', 'JP'),
City('Asia', 'Delhi', 'IN'),
City('North America', 'Mexico City', 'MX'),
City('North America', 'New York', 'US'),
City('South America', 'São Paulo', 'BR'),
]

通过函数返回列表中位于亚洲的城市。

对象引用、可变性和垃圾回收

变量不是盒子


通过变量b可以看出,如果认为b是盒子,存储盒子a的副本,那么结果就对不上了。更合理的理解是把变量视作便利贴。
因此,b=a语句不是把a盒子中的内容复制到b盒子中,而是在标注为a对象上再贴一个标注b

同一性、相等性和别名


==is之间的选择

==运算符比较两个对象的值(对象存储的数据),而is比较对象的标识。
最常使用is检查变量绑定的值是不是None。

x  is None

否定的写法是

x is not None

元组的相对不可变性

元组与多数python容器(列表、字典、集合)一样,存储的是对象的引用。如果引用的项是可变的,即便元组本身不可变,项依然可以更改。也就是说
,元组的不可变性其实是指tuple数据结构的物理内容(即存储的引用)不可变,与引用的对象无关。

相比之下,strbytesarray.array等扁平序列存储的不是引用,而是在连续的内存中存储内容的本身(字符、字节序列和数值)。


复制对象时,相等性和同一性之间的区别有更深层的影响。副本与源对
象相等,但是 ID 不同。

默认做浅拷贝

复制列表(或多数内置的可变容器)最简单的方式是使用内置的类型构造函数。例如:

对列表和其他可变序列来说,还可以使用简洁的 l2 = l1[:] 语句创建副本。
然而,构造函数或 [:] 做的是浅拷贝(即复制最外层容器,副本中的
项是源容器中项的引用)。如果所有项都是不可变的,那么这种行为没
有问题,而且还能节省内存。但是,如果有可变的项,可能就会导致意
想不到的问题。

浅拷贝的副本,可变对象跟着变化,而对象本身的变化及不可变的对象发生改变,则副本不发生变化。

为任意对象做浅拷贝和深拷贝

有时需要深拷贝(即副本不共享内部对象的引用),copy模块提供的copydeepcopy函数分别对任意对象做浅拷贝和深拷贝。
示例1:校车乘客在途中有上有下

class Bus:
    def __init__(self, passengers=None):
        if passengers is None:
            self.passengers = []
        else:
            self.passengers = list(passengers)
    def pick(self, name):
        self.passengers.append(name)
    def drop(self, name):
        self.passengers.remove(name)

copy deepcopy产生的不同效果.

浅拷贝对于可变对象,浅拷贝的副本也会跟着变化,而深拷贝引用另一个列表,因此不会变

示例2:循环引用:b引用a,又把b追加到a中;deepcopy会想办法复制a

深拷贝有时可能太深了。例如对象可能会引用不该复制的外部资源或单列。

函数的参数是引用时

Python 唯一支持的参数传递模式是共享传参(call by sharing)。多数面
向对象语言采用这一模式,包括 JavaScriptRubyJavaJava 的引用
类型是这样,原始类型按值传参)。共享传参指函数的形参获得实参引
用的副本。也就是说,函数内部的形参是实参的别名。这种模式的结果是,函数可能会修改作为参数传入的可变对象,但是无
法修改那些对象的标识(也就是说,不能把一个对象彻底替换成另一个
对象)
示例1:函数可能会修改接收到的任何可变对象

不要使用可变类型作为参数的默认值

可选参数可以有默认值,这是 Python 函数定义的一个很棒的特性,这
样我们的 API 在演进的同时能保证向后兼容。然而,应该避免使用可变的对象作为参数的默认值
示例2:可变默认值的危险性

class HauntedBus:
    """一个受幽灵乘客折磨的校车模型"""
        
    #  如果没有传入 passengers 参数,则绑定默认的列表对象(一开始是空列表)  
    def __init__(self, passengers=[]): # 
        self.passengers = passengers 
        # 这个赋值语句把 self.passengers 变成 passengers 的别名。没有
        # 提供 passengers 参数时,passengers 是默认列表的别名
        
    def pick(self, name):
        self.passengers.append(name) 
        # 在 self.passengers 上调用 .remove() 和 .append() 方法,修改
        # 的其实是默认列表,它是函数对象的一个属性。
    def drop(self, name):
        self.passengers.remove(name)


问题在于,没有指定初始乘客的 HauntedBus 实例共享同一个乘客列表。
实例化 HauntedBus 时,如果
传入乘客,则一切正常。但是,不为 HauntedBus 指定乘客的话,奇怪
的事就会发生,这是因为 self.passengers 变成了 passengers 参数
默认值的别名。出现这个问题的根源是,默认值在定义函数时求解(通
常在加载模块时),因此默认值变成了函数对象的属性。所以,如果默
认值是可变对象,而且修改了它的值,那么后续的函数调用都会受到影
响。

防御可变参数

如果你定义的函数接收可变参数,那就应该谨慎考虑调用方是否期望修
改传入的参数。例如,如果函数接收一个字典,而且在处理的过程中要修改它,那么这
个副作用要不要体现到函数外部?具体问题具体分析。这其实需要函数
的编写者和调用方达成共识。

del和垃圾回收

对象绝不会自行销毁;然而,对象不可达时,可能会被当作垃圾回
收。
首先,你可能觉得奇怪,del 不是函数而是语句,写作 del x 而不是
del(x)
其次,del 语句删除引用,而不是对象。del 可能导致对象被当作垃圾
回收,但是仅当删除的变量保存的是对象的最后一个引用时。重新绑定
也可能导致对象的引用数量归零,致使对象被销毁。

示例:没有指向对象的引用时,监控对象生命结束时的情形

上面的示例明确指出del不删除对象,但是执行del操作后可能会导致对象不可达,从而使得对象被删除。

python对不可变类型的操作

示例1:使用一个元组构建一个元组,得到的其实是同一个元组

strbytesfrozenset 实例也有这种行为。
示例2:字符串字面量可能会创建共享的对象

共享字符串字面量是一种优化措施,称为驻留(interning)。CPython
还会在小的整数上使用这个优化措施,防止重复创建“热门”数值,例如
0、1、-1 等。注意,CPython 不会驻留所有字符串和整数,驻留的条件
是实现细节,而且没有文档说明。

标签:passengers,示例,python,self,元组,--,对象,引用,第六章
From: https://www.cnblogs.com/bonne-chance/p/18218527

相关文章

  • uboot-spl 编译流程
    以下例子都以projectX项目tiny210(s5pv210平台,armv7架构)为例[uboot]uboot流程系列:[projectX]tiny210(s5pv210)上电启动流程(BL0-BL2)建议先看《[projectX]tiny210(s5pv210)上电启动流程(BL0-BL2)》,根据例子了解一下上电之后的BL0\BL1\BL2阶段,以及各个阶段的运行位置,功能。=......
  • 使用Pyftpdlib库搭建一个FTP服务器
    安装Pyftpdlib库pipinstallpyftpdlib 一键开启(本地直接开启一个简单的FTP服务器)访问 ftp://127.0.0.1:2121(默认IP为 127.0.0.1 、端口为 2121 )python-mpyftpdlib  可选参数-i 指定IP地址(默认为本机的IP地址)-p 指定端口(默认为2121)-w 写权限(默认为......
  • linux基础知识
    一、连接工具(1)(推荐,免费)FinalShell  FinalShell SSH工具,服务器管理,远程桌面加速软件,支持Windows,macOS,Linux,版本4.3.10,更新日期2023.12.31 - FinalShell官网 (hostbuf.com)(2)XShell (有家庭和学校版)(更好用,但是公司不推荐)二、查看系统查看系统内核uname -aLinux......
  • 代码与梦想:一个程序员的白日梦(367)
    第一章:时光的逆流阳光透过窗帘的缝隙,洒在了沈墨的脸上。他揉了揉眼睛,从床上坐起,却发现自己躺在一个熟悉而又陌生的房间里。墙上挂着的日历显示着一个令人难以置信的日期——2008年6月6日,高考的前一天。沈墨心中涌起了一股难以言喻的感觉,他记得自己昨晚还在为公司的项目加班到深......
  • C++17 链接 C++11 lib 出现重复定义
    C++11实现staticconstexpr是按照conststatic实现的,需要在.cpp中定义://tmp.hclassStatisTest{public:staticconstexprconstcharliteral[]="xxxliteral";};//tmp.cc#include"tmp.h"constcharStatisTest::literal[];//compile......
  • llamafactory框架下微调llama3-70b推理问题
    问题描述使用llamafactory+npulora微调llama3-70b后,最终推理出现乱码以及不能自动停止生成。如下所示:derrickroseofthechicagobullshasthemostcareerassistsamongplayerswhohaveneverbeennamedtoanall-stargamewith3,339assists.IICIII.џџџ.3......
  • 牛客小白月赛94
    A-小苯的九宫格#include<bits/stdc++.h>usingnamespacestd;intmain(){ vector<int>a(11); for(inti=1;i<=9;i++)cin>>a[i]; strings; cin>>s; for(autoi:s) cout<<a[i-'0'];return0;}......
  • C. Nikita and LCM
    原题链接题解发现一串数字的lcm一定大于等于这一串数字的最大值,所以如果整个数组的lcm大于\(a_{max}\),直接输出n否则,注意这里的思维,否则,剩余数字组成的lcm一定小于等于\(a_{max}\)且是\(a_{max}\)的因子code#include<bits/stdc++.h>#definelllonglongusingnamesp......
  • Mybatis-Plus 实现 jsonb类型的数据存取
    1、自定义类型处理器importcom.alibaba.fastjson.JSON;importcom.alibaba.fastjson.serializer.SerializerFeature;importorg.apache.ibatis.type.BaseTypeHandler;importorg.apache.ibatis.type.JdbcType;importorg.postgresql.util.PGobject;importjava.sql.Calla......
  • 使用数据处理函数
    selectvend_name,Upper(vend_name)asvend_name_upcasefromvendorsorderbyvend_nameLeft()Lenght()Locate()Lower()LTrim()Right()RTrim()Trim()Soundex()selectcust_name,cust_contactfromcustomerswherecust_contact='Y.Lie'发音......