189 8069 5689

Ruby与Python的对象系统有什么区别

本篇内容主要讲解“Ruby与Python的对象系统有什么区别”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Ruby与Python的对象系统有什么区别”吧!

创新互联专注于企业全网整合营销推广、网站重做改版、宜章网站定制设计、自适应品牌网站建设、H5响应式网站商城网站制作、集团公司官网建设、外贸网站制作、高端网站制作、响应式网页设计等建站业务,价格优惠性价比高,为宜章等各大城市提供网站开发制作服务。

属性

属性的严格定义不知道去哪里找, 这里暂且用来指对象实例用来储存自身状态的方式好了。 用途自然是储存对象的协作者与数据等。 或者干脆说成是: per-instance 的东西都叫属性1

内部访问

一般来说, 对象的内部状态轻易不向外暴露, 读写操作主要由对象的方法完成。 这种自己默默修改自身属性的存取方式我们暂时称作内部访问。

Ruby 中为每个对象提供了单独的命名空间来存放属性, 语法上 @foo 是读取,@foo = 'bar' 是写入。 而且读写语义无法通过元编程来干扰。 也不与常量查找、方法调用、局部变量存取等寻址方式相冲突。

在 Python 中这种命名空间似乎也是存在的, 而且乍一看可以通过 __dict__字典来访问2。 但由于打字太多, 实际恐怕很少有人积极使用, 更多地还是直接用外部访问的方法。 往下看。

外部访问

Ruby 默认禁止外部直接访问对象属性3, 需要我们显式地在类定义中使用attr系列方法 来显式定义供外部使用的存取方法。

Python 这边就容易得多, 自定义的 New Style Class 默认有 __dict__ 属性4, 读写全开, 可以直接用 foo.barfoo.bar = 'baz' 语法存取, 内部存取时多半也用这种语法。

这里我不想谈及定义了 __slots__ 的情况, 因为看文档里面一长串需要当心的 notes 可以猜测没什么人愿意用。 稍微 Google 一下的结果也基本证实如此。

元编程:自定义 getter/setter

两种语言都支持在语法上依然写出常规的属性取值/赋值, 而背后执行任意的代码。 常用的场景包括延迟求值, 计算属性(Calculated Attribute), 只读属性等。

在 Ruby 里由于语法糖实在太甜, 调用方法时可以省略掉括号, 能够不传参数调用的方法就是 getter, 写起来像 foo.bar。 以 = 结尾的一元方法就是 setter, 通过 foo.bar = 'baz' 就会调用到。 前面提到的 attr 系列方法 也只是按照这个接口来定义方法, 并非特殊的语言关键字。

至于 Python, 只需 getter 时还好说, 直接用 @property 装饰器就好。 但需要允许外部只读访问属性时就有些麻烦。 读写控制要由 property descriptor 来实现, 为了自定义一个只读 descriptor 写起来像这样:

EDIT: 明显下面的代码是不对的, 当时我在想什么。 还好真实世界中一般都用下划线方案而不是用这种方案来满足语义纯化论者。

class Foo(object):
    bar = property()
    @bar.setter
    def bar(self, value):
        raise AttributeErrorFoo().bar = 'shit' # => 抛 AttributeError 异常

这样在内部访问中要写入属性时就要被迫改用这种伤键盘的写法:self.__dict__['bar'] = 'blah'。 所以现实生活中人们往往用下划线开头表达私有属性, 然后定义一个去掉开头下划线的 getter 来提供只读访问了事。

+1 for Ruby

到这里已经可以总结出我偏好 Ruby 的一点原因:

对属性的内部与外部存取做出明确区分, 默认不提供外部直接存取。 且两种存取方式的语法都不难写。 鼓励开发者在设计时考虑好封装问题。 而 Python 惯用的方式是下划线标识私有属性, 难免会增加代码量。

接下来如果再写下去要一并引入很多对象模型的重点问题, 恐怕就要被标记 TL;DR 了。 所以先到这吧。

  1. 未来谈及方法解析的时候会引入 per-instance 的方法定义, 从而毁掉这个不严格的描述。

  2. 但是你没法通过自定义 __dict__ 返回值来扰乱属性专有字典。  是的, 在这两种语言元编程的能力下, 可以做出很多出格的事情来。 本文只能在假设开发者不会积极地乱来的基调下展开讨论。

  3. 当然你可以用 instance_variable_{get,set,s} 等方法来访问。 避而不谈的理由见另一个脚注。

  4. object 类自己却没有定义 __dict__, 其实例也没有。 所以尽管这样一个空的 New Style Class class Foo(object): pass 是 object 的直接子类, 两个类的实例的行为却大不相同。

到此,相信大家对“Ruby与Python的对象系统有什么区别”有了更深的了解,不妨来实际操作一番吧!这里是创新互联网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!


网站名称:Ruby与Python的对象系统有什么区别
分享URL:http://cdxtjz.cn/article/gjoddp.html

其他资讯