博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
《Python面向对象编程指南》——2.8 __new__()方法和不可变对象
阅读量:6984 次
发布时间:2019-06-27

本文共 1702 字,大约阅读时间需要 5 分钟。

本节书摘来自异步社区《Python面向对象编程指南》一书中的第2章,第2.8节,作者[美]Steven F. Lott, 张心韬 兰亮 译,更多章节内容可以访问云栖社区“异步社区”公众号查看。

2.8 __new__()方法和不可变对象

__new__方法的一个用途是初始化不可变对象。__new__()方法中允许创建未初始化的对象。这允许我们在__init__()方法被调用之前先设置对象的属性。

由于不可变类的__init__()方法很难重载,因此__new__方法提供了一种扩展这种类的方法。

下面是一个错误定义的类,我们定义了float的一个包含单位信息的版本。

class Float_Fail( float ):   def __init__( self, value, unit ):     super().__init__( value )     self.unit = unit

我们试图(不合理地)初始化一个不可变对象。

下面是当我们试图使用这个类时会发生的情况。

>>> s2 = Float_Fail( 6.5, "knots" )Traceback (most recent call last): File "
", line 1, in
TypeError: float() takes at most 1 argument (2 given)

可以看到,对于内置的float类,我们不能简单地重载__init__方法。对于其他的内置不可变类型,也有类似的问题。我们不能在不可变对象self上设置新的属性值,因为这是不可变性的定义。我们只能在对象创建的过程中设置属性值,对象创建之后__new__()方法就会被调用。

__new__()方法天生就是一个静态方法。即使没有使用@staticmethod修饰符,它也是静态的。它没有使用self变量,因为它的工作是创建最终会被赋值给self变量的对象。

这种情况下,我们会使用的方法签名是__new__( cls, args, *kw)。cls变量是准备创建的类的实例。下一个部分关于元类型的例子,会比这里展示的args的参数序列更加复杂。

__new__()方法的默认实现如下。

return super().__new__( cls )将调用基类的__new__()方法创建对象。这个工作最终委托给了object.__new__(),这个方法创建了一个简单的空对象。除了cls以外,其他的参数和关键字最终都会传递给__init__()方法,这是Python定义的标准行为。

除了有下面的两个例外,这就是我们期望的行为。

  • 当我们需要继承一个不可变的类的时候,我们会在后面的部分详细讲解。
  • 当我们需要创建一个元类型的时候,这是下一个部分的主题,因为它与创建不可变对象是完全不同的。

当创建一个内置的不可变类型的子类时,不能重载__init__()方法。取而代之的是,我们必须通过重载__new__()方法在对象创建的过程中扩展基类的行为。下例是扩展float类的正确方式。

class Float_Units( float ):   def __new__( cls, value, unit ):     obj= super().__new__( cls, value )     obj.unit= unit     return obj

上面的代码在对象创建的过程中设置了一个属性的值。

下面的代码使用上面定义的类创建了一个带单位的浮点数。

>>>speed= Float_Units( 6.5, "knots" )>>>speed6.5>>>speed * 1065.0>>> speed.unit'knots'

注意,像speed * 10这种表达式不会创建一个Float_Units对象。这个类的定义继承了float中所有的运算符;float的所有算术特殊方法也都只会创建float对象。创建Float_Units对象会在第7章“创建数值类型”中介绍。

转载地址:http://rtxpl.baihongyu.com/

你可能感兴趣的文章
阿里云Redis (安装包安装篇)
查看>>
Spring Bean的装配(非XML文件方式)
查看>>
100万“愤怒的小鸟”:中国手机开发者生存调查
查看>>
centos 6.3 x86_64安装32位JDK的问题
查看>>
springmvc学习笔记(17)-上传图片
查看>>
驰骋工作流引擎表单设计控件-字段类控件(2)
查看>>
java高级-多线程编程
查看>>
spark内核回顾思考 RDD
查看>>
导出Android手机应用apk
查看>>
高并发分布式系统中生成全局唯一(订单号)Id
查看>>
在 iOS 应用中直接跳转到 AppStore 的方法
查看>>
IOS 委托和协议区别和联系 (-)
查看>>
通过JDBC连接取得数据库相关的元数据
查看>>
CentOS常用到的查看系统命令
查看>>
Validform使用入门
查看>>
Jfinal碰到的问题记录
查看>>
Kettle7 java 远程执行Trans/Job
查看>>
Python Socket 编程
查看>>
jenkins ssh发布配置
查看>>
Guava新集合-Multiset
查看>>