Python 通过继承实现标准对象的子类
idict是dict的子类,它的键值和属性是同步的,并且有强大的默认值机制.
例如,假设x是idict的一个实例,且x['a']['b']=12,则有x.a.b=12.反之亦然;
假设'c'不在x的键集合,那么尝试访问x['c']或者x.c,均会直接初始化默认值.
class idict(dict):
"super dict class, attributes and keys are equal"
def __init__(self,d={},dft=None):
idict.dft=dft
for k,v in d.items():
if isinstance(v,dict):
self.__setitem__(k,idict(v,idict.dft))
else:
self.__setitem__(k,v)
def __setitem__(self,k,v):
dict.__setitem__(self,k,v)
dict.__setattr__(self,k,v)
def __missing__(self,k):
self.__setitem__(k,idict.dft)
return idict.dft
__setattr__=__setitem__
__getattr__=__missing__
- 字典访问d['k']和属性访问d.k有着微妙的关系.
对于常规访问,字典端对应__getitem__,属性端对应__getattribute__
对于缺失访问,字典端对应__missing__,属性端对应__getattr__
对于添加或更新值,字典端对应__setitem__,属性端对应__setattr__
- __init__中定义一个类属性idict.dft=dft是非常有必要的.(为什么不self.dft=dft?)
- __init__能调用实例的__setitem__方法,也能递归调用父类idict.
- 子类的__init__未必总是需要调用父类的__init__.此例中,通过递归idict(v,idict.dft)初始化实例属性,非常精妙.
- 重写特殊方法的最简单的工具是直接调用父类的同类方法.例如在定义idict的__setitem__方法时,用到了dict.__setitem__
idict有什么实际的好处?
首先能够设置默认值,这样就能减少一些判断.这相当于dict.setdefault(k,v),但是idict[k]不是优雅许多吗?
其次属性形式的控制风格,便于写代码(虽然看起来有些无聊).例如idict['a']['b']['c']=2,就没有idict.a.b.c=2优雅.
总之,通过这次定制dict类,我发现Python面向对象所蕴含的强大力量.
测试代码:
if __name__=='__main__':
dic={'one':1,
'two':{
'four':4,
'five':{
'six':6,
'seven':7,}},
'three':3} cdic=idict(dic,'default') print('-------------------the start state of cdic-------------------------------------------')
print(cdic)
print('-------------------query in two ways-------------------------------------------')
print('cdic.two.five-->',cdic.two.five)
print("cdic['two']['five']-->",cdic['two']['five'])
print('cdic.two.five.six-->',cdic.two.five.six)
print("cdic['two']['five']['six']-->",cdic['two']['five']['six']) print('-------------------update in two ways-------------------------------------------')
cdic['two']['five']['six']=7
print("cdic['two']['five']['six']=7")
print("cdic.two.five.six-->",cdic.two.five.six ) cdic.two.five.six=6
print("cdic.two.five.six=6")
print("cdic['two']['five']['six']-->",cdic['two']['five']['six']) print('-------------------add new one in two ways-------------------------------------------') cdic['two']['five']['eight']=8
print("cdic['two']['five']['eight']=8")
print("cdic.two.five.eight-->",cdic.two.five.eight) cdic.two.five.nine=9
print("cdic.two.five.nine=9")
print("cdic['two']['five']['nine']-->",cdic['two']['five']['nine']) print('-------------------query and set default in two ways-------------------------------------------')
print("cdic['ten']-->",cdic['ten'])
print("cdic.eleven-->",cdic.eleven)
print("cdic.two.five.twelve-->",cdic.two.five.twelve)
print("cdic['two']['five']['thirteen']-->",cdic['two']['five']['thirteen']) print('-------------------the final state of cdic-------------------------------------------')
print('dict view--print(cdic):')
print(cdic)
print('\nattributes view--print(cdic.__dict__):')
print(cdic.__dict__)
print() def show(d):
for k,v in d.items():
if isinstance(v,(str,int)):
yield '%s->%s'%(k,v)
else:
for i in show(v):
yield '%s.%s'%(k,i) for i in show(cdic):
print('cdic.'+i)
测试结果:
>>>
-------------------the start state of cdic-------------------------------------------
{'two': {'five': {'seven': 7, 'six': 6}, 'four': 4}, 'one': 1, 'three': 3}
-------------------query in two ways-------------------------------------------
cdic.two.five--> {'seven': 7, 'six': 6}
cdic['two']['five']--> {'seven': 7, 'six': 6}
cdic.two.five.six--> 6
cdic['two']['five']['six']--> 6
-------------------update in two ways-------------------------------------------
cdic['two']['five']['six']=7
cdic.two.five.six--> 7
cdic.two.five.six=6
cdic['two']['five']['six']--> 6
-------------------add new one in two ways-------------------------------------------
cdic['two']['five']['eight']=8
cdic.two.five.eight--> 8
cdic.two.five.nine=9
cdic['two']['five']['nine']--> 9
-------------------query and set default in two ways-------------------------------------------
cdic['ten']--> default
cdic.eleven--> default
cdic.two.five.twelve--> default
cdic['two']['five']['thirteen']--> default
-------------------the final state of cdic-------------------------------------------
dict view--print(cdic):
{'two': {'five': {'eight': 8, 'nine': 9, 'twelve': 'default', 'seven': 7, 'thirteen': 'default', 'six': 6}, 'four': 4}, 'ten': 'default', 'one': 1, 'eleven': 'default', 'three': 3} attributes view--print(cdic.__dict__):
{'two': {'five': {'eight': 8, 'nine': 9, 'twelve': 'default', 'seven': 7, 'thirteen': 'default', 'six': 6}, 'four': 4}, 'ten': 'default', 'one': 1, 'eleven': 'default', 'three': 3} cdic.two.five.eight->8
cdic.two.five.nine->9
cdic.two.five.twelve->default
cdic.two.five.seven->7
cdic.two.five.thirteen->default
cdic.two.five.six->6
cdic.two.four->4
cdic.ten->default
cdic.one->1
cdic.eleven->default
cdic.three->3
Python 通过继承实现标准对象的子类的更多相关文章
- sqlalchemy mark-deleted 和 python 多继承下的方法解析顺序 MRO
sqlalchemy mark-deleted 和 python 多继承下的方法解析顺序 MRO 今天在弄一个 sqlalchemy 的数据库基类的时候,遇到了跟多继承相关的一个小问题,因此顺便看了一 ...
- python基础——继承和多态
python基础——继承和多态 在OOP程序设计中,当我们定义一个class的时候,可以从某个现有的class继承,新的class称为子类(Subclass),而被继承的class称为基类.父类或超类 ...
- Python进阶-继承中的MRO与super
Python进阶-继承中的MRO与super 写在前面 如非特别说明,下文均基于Python3 摘要 本文讲述Python继承关系中如何通过super()调用"父类"方法,supe ...
- python基础——继承实现的原理
python基础--继承实现的原理 1 继承顺序 class A(object): def test(self): print('from A') class B(A): def test(self) ...
- python基础——继承与派生、组合
python基础--继承与派生 1 什么是继承: 继承是一种创建新的类的方式,在python中,新建的类可以继承自一个或者多个父类,原始类成为基类或超累,新建的类成为派生类或子类 1.1 继承分为:单 ...
- python之继承、抽象类、新式类和经典类
一.上节补充1.静态属性静态属性 : 类的属性,所有的对象共享这个变量 如果用对象名去修改类的静态属性:在对象的空间中又创建了一个属性,而不能修改类中属性的值 操作静态属性应该用类名来操作 例1:请你 ...
- python 面向对象 继承 派生 组合
具体参考博客:http://www.cnblogs.com/linhaifeng/articles/6182264.html#_label12 一.面向对象 面向对象:对象与对象之间的相互交互,不可预 ...
- Python类继承(转发)
目录 一.概述 二.类的继承 2.1 继承的定义 2.2 构造函数的继承 2.3 子类对父类方法的重写 三.类继承的事例 回到顶部 一.概述 面向对象编程 (OOP) 语言的一个主要功能就是“继承”. ...
- python中继承和多态
继承和多态 继承 引入继承 我们有这样一个需求 模仿英雄联盟定义两个英雄类 1.英雄要有昵称.攻击力.生命值属性 2.实例化出两个英雄对象 3.英雄之间可以互殴,被殴打的一方掉血,血量小于0则判断为死 ...
随机推荐
- [LeetCode] Find the Derangement of An Array 找数组的错排
In combinatorial mathematics, a derangement is a permutation of the elements of a set, such that no ...
- NC帮助文档网址
NC帮助文档: https://wenku.baidu.com/view/2d05a77c0b4e767f5acfceb6.html NC方法总结: ...
- svg从入门到装逼(一)
svg文件是基于xml的矢量图,而canvas是基于html和js的位图.关于两者的比较,在粗就不赘述了. 1. 首先来上一个svg的基本结构: <?xml version="1.0 ...
- [HNOI2004]L语言
题目描述 标点符号的出现晚于文字的出现,所以以前的语言都是没有标点的.现在你要处理的就是一段没有标点的文章. 一段文章T是由若干小写字母构成.一个单词W也是由若干小写字母构成.一个字典D是若干个单词的 ...
- 【bzoj4445 scoi2015】小凸想跑步
题目描述 小凸晚上喜欢到操场跑步,今天他跑完两圈之后,他玩起了这样一个游戏. 操场是个凸 nn 边形, nn 个顶点按照逆时针从 00 ∼ n - 1n−1 编号.现在小凸随机站在操场中的某个位置,标 ...
- hdu 3473 划分树
Minimum Sum Time Limit: 16000/8000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Tot ...
- UDA机器学习基础—评估指标
这里举例说明 混淆矩阵 精确率 召回率 F1
- Tomcat 报错的解决方法:The APR based Apache Tomcat Native library which allows optimal
下载 http://tomcat.heanet.ie/native/1.1.12/binaries/win32/tcnative-1.dll将这个文件复制到C:\WINDOWS\system32\,. ...
- Exchange Server 2010升级到Exchange Server 2016
Hello各位小伙伴们,失踪人口回归啦~~~这次和大家分享Exchange Server 2010升级到Exchange Server 2016的方法.正式开始前先啰嗦几句,为什么我要写这篇文章呢?一 ...
- tf.nn.conv2d 和 tf.nn.max_pool 中 padding 分别为 'VALID' 和 'SAME' 的直觉上的经验和测试代码
这个地方一开始是迷糊的,写代码做比较分析,总结出直觉上的经验. 某人若想看精准的解释,移步这个网址(http://blog.csdn.net/fireflychh/article/details/73 ...