一个模拟使用字典存储属性的示例Coding。。。刚意识到几乎所有的数据结构都是字典(dict),在定义时有诸多麻烦:
- 设置初始值,频繁使用defaultdict
- 影响效率,每次为字典内value-list,有频繁的赋值操作
- 不方便维护,代码量大
网上搜索后发现也有coder有相关研究,特此总结一下有关知识
参考自:http://www.cocoachina.com/articles/48042
一个模拟bug列表的示例,包含有以下方法与 key-values
# personels: dict
# personels.key: 唯一的account
# personels.value: 如以下的数据
personels=defaultdict(lambda: {
"displayname": "UNKNOWN",
"account": "UNKNOWN",
"bugnums": {
"OPEN": 0,
"TOTAL": 0
},
"buglist": [],
}
# 用面向对象设计,使用列表 或 字典(唯一值为键)存储
class personel:
def __init__(self,dname,account,buglist)
self.displayname=dname
self.account=account
self.buglist=buglist
self.OPENbugNums=... #对buglist处理
self.TOTALbugNums=...
出现了个需求,将personel按照部门(department)分类
于是就改为
from typing import DefaultDict
personels=DefaultDict(lambda: {
"displayname": "UNKNOWN",
"account": "UNKNOWN",
"bugnums": {
"OPEN": 0,
"TOTAL": 0
},
"buglist": [],
})
# departments: dict,默认值-建对为 personels
departments=DefaultDict(lambda: {
"personels": personels,
"department_bugnums":{
"OPEN": 0,
"TOTAL": 0
},
"buglist": []
})
为该字典添加实例化对象,打印出来:
departments['中国软件部'] print(departments) departments: defaultdict(at 0x7f79c2ec1ee0>, { '中国软件部': { 'personels': defaultdict( at 0x7f79c30c4160>, {}), 'department_bugnums': { 'OPEN': 0, 'TOTAL': 0}, 'buglist': []} } )
添加buglist,并且修改department_bugnums:
departments['中国软件部']['buglist'].append(bug) departments['中国软件部']['department_bugnums']['TOTAL']+=1 if bug is openbug: departments['中国软件部']['department_bugnums']['OPEN']+=1
只需要查询、打印输出(做表格)功能,目前来说用字典还是比较方便的,但是又想到类似也完全能够用 面向对象 来设计
以下为向参考文档 COPY下来的
我以为:
- 字典优点:
-更快和/或更高的内存效率- 字典缺点:
- 无法通过静态代码检查程序捕获一些错误
- 可能永远不会显示或知道所有窗口小部件属性的完整列表- 对象优点:
- 确切知道’Widget’是由什么组成的
- 使用静态代码检查器可能会捕获错误(尽管使用** magic会阻止其中一些)- 对象缺点:
- 更慢和/或更低的内存效率
实际上:
参考自 python 官方文档
python __slots__详解 上
python __slots__详解 下
总结为:
- 使用字典没有任何好处,对象的数据存储在__dict__ ,也是存储在字典中
- 使用对象为了实现对象的绑定属性和方法,用的是__slots__:
- 动态语言,允许对象定义在对象内实现未绑定的属性,意思是
class a(object):
pass
vara=a()
vara.name="Hello"
print(vara.name)
vara.age=13
print(vara.age)
#OUT
Hello
123
这竟然是允许的,证明了类内属性是存储在字典__dict__ 里的
- 为了达到限制的目的,可以定义__slots__ ,来限制该class能添加的属性,如下:
from os import name
class a(object):
def __init__(self,name="UNKNOWN",age=0):
self.name=name
self.age=age
class aslot(object):
__slots__=('name','age')
def __init__(self,name="UNKNOWN",age=0) -> None:
super().__init__()
self.name=name
self.age=age
vara=a()
varaslot=aslot()
vara.id='1'
# varaslot.id='1'
print("dir(a): {}".format(dir(a)))
print("dir(aslot): {}".format(dir(aslot)))
print("dir(vara): {}".format(dir(vara)))
print("dir(varaslot): {}".format(dir(varaslot)))
OUT
dir(a): [’_class_’, ‘_delattr_’,
′
_
_
d
i
c
t
_
_
′
color{#FF3030}{'__dict__'}
′__dict__′, ‘_dir_’, ‘_doc_’, ‘_eq_’, ‘_format_’, ‘_ge_’, ‘_getattribute_’, ‘_gt_’, ‘_hash_’, ‘_init_’, ‘_init_subclass_’, ‘_le_’, ‘_lt_’, ‘_module_’, ‘_ne_’, ‘_new_’, ‘_reduce_’, ‘_reduce_ex_’, ‘_repr_’, ‘_setattr_’, ‘_sizeof_’, ‘_str_’, ‘_subclasshook_’, ‘_weakref_’]
dir(aslot): [’_class_’, ‘_delattr_’, ‘_dir_’, ‘_doc_’, ‘_eq_’, ‘_format_’, ‘_ge_’, ‘_getattribute_’, ‘_gt_’, ‘_hash_’, ‘_init_’, ‘_init_subclass_’, ‘_le_’, ‘_lt_’, ‘_module_’, ‘_ne_’, ‘_new_’, ‘_reduce_’, ‘_reduce_ex_’, ‘_repr_’, ‘_setattr_’, ‘_sizeof_’, ‘
′
_
_
s
l
o
t
s
_
_
′
color{#FF3030}{'__slots__'}
′__slots__′’, ‘_str_’, ‘_subclasshook_’,
′
a
g
e
′
,
′
n
a
m
e
′
color{#FF3030}{'age', 'name'}
′age′,′name′]
dir(vara): [’_class_’, ‘_delattr_’,
′
_
_
d
i
c
t
_
_
′
color{#FF3030}{'__dict__'}
′__dict__′, ‘_dir_’, ‘_doc_’, ‘_eq_’, ‘_format_’, ‘_ge_’, ‘_getattribute_’, ‘_gt_’, ‘_hash_’, ‘_init_’, ‘_init_subclass_’, ‘_le_’, ‘_lt_’, ‘_module_’, ‘_ne_’, ‘_new_’, ‘_reduce_’, ‘_reduce_ex_’, ‘_repr_’, ‘_setattr_’, ‘_sizeof_’, ‘_str_’, ‘_subclasshook_’, ‘_weakref_’,
′
a
g
e
′
,
′
n
a
m
e
′
,
′
i
d
′
color{#FF3030}{'age', 'name', 'id'}
′age′,′name′,′id′]
dir(varaslot): [’_class_’, ‘_delattr_’, ‘_dir_’, ‘_doc_’, ‘_eq_’, ‘_format_’, ‘_ge_’, ‘_getattribute_’, ‘_gt_’, ‘_hash_’, ‘_init_’, ‘_init_subclass_’, ‘_le_’, ‘_lt_’, ‘_module_’, ‘_ne_’, ‘_new_’, ‘_reduce_’, ‘_reduce_ex_’, ‘_repr_’, ‘_setattr_’, ‘_sizeof_’,
′
_
_
s
l
o
t
s
_
_
′
color{#FF3030}{'__slots__'}
′__slots__′, ‘_str_’, ‘_subclasshook_’,
′
a
g
e
′
,
′
n
a
m
e
′
color{#FF3030}{'age', 'name'}
′age′,′name′]
粗浅的看:
- 未实例化的普通类,无init内的变量;已实例化的类,有init内的变量。
- 未实例化的slots类,已实例化的slots类,都有init内的变量



