对象、属性、映射,喔我的
或者,IC UC 我们都 C 以获取 ICs。在许多动态类型的编程语言中,对象看起来像一个将名称映射到值的大映射。这些语言鼓励这种灵活性。以 Python 为例:class C : def __init__ ( self ): self . a = 1 self . b = 2 或 Ruby:class C def initialize @a = 1 @b = 2 end end 或 JavaScript 1 : let obj = {}; obj . a = 1 ; obj . b = 2 ; 这可能鼓励虚拟机实现者使用哈希表来建模对象属性。毕竟,哈希表非常擅长将名称映射到值。这里有一个 Python 草图,展示了这个对象模型的样子。因为这只是一个草图,它使用 write_attr 和 read_attr,而不是你所在编程语言中更常见的语法。MISSING = object () class Instance : def __init__ ( self ): # TODO: 你的对象系统的其余部分 self . cls = ... self . _fields = {} def read_attr ( self , fieldname ): return self . _fields . get ( fieldname , MISSING ) def write_attr ( self , fieldname , value ): self . _fields [ fieldname ] = value obj = Instance () obj . write_attr ( "a" , 1 ) obj . write_attr ( "b" , 2 ) print ( obj . read_attr ( "a" ) + obj . read_attr ( "b" )) 这有它的好处:它容易理解…呃,好吧,也许就这些。它也有它的缺点:它为一个非常常见的操作使用了哈希表:虽然从技术上讲这是 O(1),但哈希和探查非常慢,它有一个间接性:从对象跳转到它的独立哈希表字段存储需要大量的依赖内存加载。对象属性经常被访问,因此应该内联存储在对象上,而不是另一个内存访问(以及可能的缓存未命中)之外。这是一个哈希表没有内部碎片的非常好的例子。这意味着字面上每个操作 a.b 都在执行数百或数千条 CPU 指令,包括多个依赖的内存加载。这对性能不好。因此,运行时实现者倾向于实现一种被称为映射、布局、形状、隐藏类或结构的东西,或者可能还有一个我不知道的第六个秘密名称,来优化属性的读取、写入和存储。但是这个形状代码看起来如何?它实际上如何帮助性能?许多大型生产运行时有非常复杂的代码并具有特定领域的边缘案例,因此它们可能无法帮助我们掌握基础知识。而许多博客文章,尽管是优秀的高层次概述,但在实现方面欠缺。因此我们再次开始博客,写的内容与其他人之前已写过的相同。希望你应能写一页代码,并一次性掌握整个内容,500 行或更少。我决定再次仔细阅读 CF Bolz-Tereick 的《一个简单的对象模型》,这是它应有的详尽读物。在过去,我尝试过几次,但因为它对 Python 的建模相当逼真,而 Python 的对象模型实在太复杂,因此没有阅读下去。但这次我是否彻底读过?好吧,不是。这次我允许自己略读与类和方法相关的部分,而是专注于实例属性和映射部分。在 CF 的帖子中,有一个非常干净的映射系统的核心,我想对此进行实验,所以我提取了这个部分。CF 的帖子一开始与我们自己的草图非常相似,将对象建模为无序的属性映射。它还填补了我之前遗漏的一些与类相关的 TODO 内容。我将在这里复制我的减缩实现,以便你可以瞧瞧:# 基础对象模型代码:class Base : def __init__ ( self , cls , fields ): self . cls = cls self . _fields = fields def read_attr ( self , fieldname ): return self . _read_dict ( fieldname ) def write_attr ( self , fieldname , value ): return self . _write_dict ( fieldname , value ) def _read_dict ( self , fieldname ): return self . _fields . get ( fieldname , MISSING ) def _write_dict ( self , fieldname , value ): self . _fields [ fieldname ] = value MISSING = object () class Instance ( Base ): def __init__ ( self , cls : "Class" ): super (). __init__ ( cls , {}) class Class ( Base ): def __init__ ( self , name , base_class , fields , metaclass ): super (). __init__ ( metaclass , fields ) self . name = name self . base_class = base_class OBJECT = Class ( name = "object" , base_class = None , fields = {}, metaclass = None ) TYPE = Class ( name = "type" , base_class = OBJECT , fields = {}, metaclass = None ) TYPE . cls = TYPE OBJECT . cls = TYPE 你可以像这样使用(测试代码也取自 CF 的帖子):A = Class ( name = "A" , base_class = OBJECT , fields = {}, metaclass = TYPE ) obj = Instance ( A ) obj . write_attr ( "a" , 1 ) assert obj . read_attr ( "a" ) == 1 obj . write_attr ( "b" , 5 ) assert obj . read_attr ( "a" ) == 1 assert obj . read_attr ( "b" ) == 5 obj . write_attr ( "a" , 2 ) assert obj . read_attr ( "a" ) == 2 assert obj .
阅读全文 →本站免费、广告极少。如果觉得有帮助,可以请我们喝杯咖啡 —— 任何金额都对持续运营有实际帮助。
☕请我喝杯咖啡