Python:优先使用对象存储数据(而不是字典)

Coding。。。刚意识到几乎所有的数据结构都是字典(dict),在定义时有诸多麻烦:

  1. 设置初始值,频繁使用defaultdict
  2. 影响效率,每次为字典内value-list,有频繁的赋值操作
  3. 不方便维护,代码量大

网上搜索后发现也有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(<function <lambda> at 0x7f79c2ec1ee0>, {
	'中国软件部': {
		'personels': defaultdict(<function <lambda> 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下来的

优先使用Python中的对象字典

我以为:

  • 字典优点:
    -更快和/或更高的内存效率
  • 字典缺点:
    - 无法通过静态代码检查程序捕获一些错误
    - 可能永远不会显示或知道所有窗口小部件属性的完整列表
  • 对象优点:
    - 确切知道’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内的变量
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值