流畅的python笔记(十九)动态属性和特性

目录

前言

一、使用动态属性转换数据

接下来示例中使用JSON格式数据源

使用动态属性访问JSON类数据

处理无效属性名

使用__new__方法以灵活的方式创建对象

使用shelve模块调整OSCON的JSON数据源的结构

使用特性获取链接的记录

二、使用特性验证属性

LineItem类第一版:表示订单中商品的类

LineItem类第二版:能验证值的特性

三、特性全解析

property类

特性会覆盖实例属性

特性的文档

四、定义一个特性工厂

五、处理属性删除操作

六、处理属性的重要属性和函数

影响属性处理方式的特殊属性

处理属性的内置函数

处理属性的特殊方法


前言

python中,数据的属性和处理数据的方法统称属性attribute,即方法只是可调用的属性。除了这二者之外,我们还可以创建特性property,在不改变类接口的前提下,使用存取方法(即读值方法和设值方法)修改数据属性。

        python使用点号访问属性时,比如obj.attr,python解释器会调用特殊的方法(如__getattr__和__setattr__)计算属性。用户自定义的类可以通过__getattr__方法实现虚拟属性,当访问不存在的属性时,即时计算属性的值。

        动态创建属性是一种元编程,框架的作者经常这么做。然而在python中相关的技术十分简单,任何人都可以使用。

一、使用动态属性转换数据

接下来示例中使用JSON格式数据源

图示JSON数据源中只列出了4条记录。整个数据集是一个JSON对象,里边有一个键"Schedule",这个键对应的值也是一个映像(相当于字典),有四个键:"conferences"、"events"、"speakers"和"venues"。这4个键对应的值都是一个记录列表,示例中各个列表中只有一条记录,每条记录都是一个字典。在完整的数据集中,列表中有成百上千条记录。不过"conferences"键对应的列表中只有一条记录。这四个列表中每条记录都有一个名为"serial"的字段,这是元素在各个列表中的唯一标识符。

        第一个脚本:下载JSON数据源。

  1.  如果需要下载,就发出提醒信息。
  2.  在with语句中使用两个上下文管理器,分别用于读取和保存远程文件。即把url的远程内容读取出来然后写入本地的JSON文件。
  3.  json.load函数解析JSON文件,返回python原生对象。在这个数据源中有这几种数据类型:dict、list、str、int。

有了以上代码,就可以审查JSON数据源中的任何字段:

  1.  feed = json.load(fp),feed是JSON的解析结果,feed本质是python的原生类型对象,即一个字典,里边嵌套着字典和列表,存储着字符串和整数。
  2.  列出"Schedule"键中的4个记录集合。
  3.  显示4个记录集合中的记录数量。
  4.  深入嵌套的字典和列表,获取最后一个演讲者的名字。
  5.  获取那位演讲者的编号。
  6.  每个事件都有一个'speakers'字段,列出0个或多个演讲者的编号。

使用动态属性访问JSON类数据

上边示例中feed字典要用feed['Schedule']['events'][40]['name']来获取到具体的某个字段值,这种句法很冗长。JavaScript中,可以使用feed.Schedule.events[40].name获取那个值。下面用python实现了一个FrozenJson类可达到同样效果,但是只支持读取数据,该类能递归,自动处理嵌套的字典和列表。

  1. 传入嵌套的字典和列表组成的raw_feed,创建一个FrozenJSON实例。
  2. FrozenJSON实例能使用属性表示法遍历嵌套的字典,这里我们speakers列表中的元素数量,其中的元素都是字典。
  3. 使用底层字典的方法,.keys(),获取字典中所有的键。
  4. 使用items方法,获取字典中各个元素组成的列表 [key, value],然后显示各个集合中的元素数量,这里的value是一个列表,列表中的各个元素都是字典。
  5. feed.Schedule.speakers仍是列表,但如果列表里的元素是映射,即speakers[-1]是映射,则会被转换成FrozenJSON对象。
  6. events列表中的40号元素是一个字典,现在变成了一个FrozenJSON实例。
  7. talk是events列表中的第40个元素,talk本质是字典,其有一个speakers键,对应值是列表。
  8. 读取不存在的属性会抛出KeyError异常,而不是通常抛出的AttributeError异常。

下边是FrozenJSON对象的实现:

  1. 使用mapping参数创建一个字典,作为FrozenJSON类的实例属性。这样做目的有二:一是确保传入的是字典或者能转成成字典的对象,二是为安全起见创建了一个副本。
  2. 仅当按实例属性---类属性---继承树搜寻不到指定名称的属性(数据属性和方法统称为属性)时才调用__getattr__方法。
  3. 如果name是FrozenJSON类的实例属性__data的属性,返回那个属性。
  4. 否则,从self.__data中获取name键对应的元素,返回调用FrozenJSON.build()方法得到的结果。
  5. 用@classmethod修饰的方法是类方法,经常用这种方法来实现一个备选构造方法,比如这里的build就是一个备选构造方法。
  6. 如果obj是映射,那么就构建一个FrozenJSON对象,
  7. 如果是MutableSequence对象,这里必然是列表,因此把列表obj中的每个元素递归地传给build方法,列表推导式构建出一个列表。
  8. 如果既不是字典也不是列表,那么原封不动地返回元素。

处理无效属性名

FrozenJSON类有个缺陷:没有对名称为python关键字地属性做特殊处理,比如以如下方式构建一个对象:

此时用grad.class是无法读取对应的值的,因为在python中class是保留字:

这个时候可以用getattr(grad, 'class')来读取对应的属性:

但是Frozen类的目的是为了便于用 '.' 来访问数据,因此更好的方法是检查传给FrozenJSON.__init__方法的映射中是否有键的名称是关键字,如果有,那么在键名后加上_,然后就可以通过以下方式读取了:

FrozenJSON类的__init__方法改成如下所示:

 

  1.  先导入keyword模块,然后用keyword.iskeyword()来判断某个键是不是python保留的关键字。</
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值