美文网首页
实例就地操作类属性

实例就地操作类属性

作者: 南瓜豆腐foobar | 来源:发表于2019-07-18 17:29 被阅读0次

Python 中,类实例可以引用类的属性,就地操作符可以就地修改一个可变对象。那么通过实例引用一个可变类型的类属性,并进行就地操作,会产生什么结果?我开始的推测是类的属性会被改变但不会创建实例的属性,那实际的结果是什么呢?

试一下:

class T:
    li = []
t = T()
t.li += 'abc'
print(t.__dict__)  # t 的属性中有 li,值为 ['a', 'b', 'c']
print(T.__dict__)  # T 的属性中有 li,值为 ['a', 'b', 'c']

果然翻车了,先说下我的思路:

  1. t.li 是引用的类属性 li,即 t.li 指向的是 T.li 的地址;
  2. 对列表的原地操作,只会改变列表的值,但不会改变其内存地址

基于上以上两点的认知,所以我推测不会创建实例 tli 属性。但事实很打脸,为此我查了下官方文档。文档在赋值语句的介绍中指出:

如果该对象为类实例并且属性引用在赋值运算符的两侧都出现,则右侧表达式 a.x 可以访问实例属性或(如果实例属性不存在)类属性。 左侧目标 a.x 将总是设定为实例属性,并在必要时创建该实例属性。 因此,a.x 的两次出现不一定指向相同的属性:如果右侧表达式指向一个类属性,则左侧表达式会创建一个新的实例属性作为赋值的目标:

class Cls:
    x = 3             # class variable
inst = Cls()
inst.x = inst.x + 1   # writes inst.x as 4 leaving Cls.x as 3

文档中说的很清楚,那么回到我们上面的测试:

t.li += 'abc'

这条语句可以理解为 t.li = t.li + list('abc'),这样可以解释为什么会创建 t 实例的属性,但是无法解释类 T 的属性 li 的值为什么会改变。继续查文档,在标准库的 operater 模块中,有关于原地操作符的介绍:

Many operations have an "in-place" version. Listed below are functions providing a more primitive access to in-place operators than the usual syntax does; for example, the statement x += y is equivalent to x = operator.iadd(x, y).

大概的意思:很多操作符都有一个”就地操作“版本。下列的函数提供了一种比常规语法更原始的方式实现就地操作,比如 x +=y 等效于 x = operator.iadd(x, y)

好了,现在研究下 operator.iadd

import operator
li = []
new_li = operator.iadd(li, 'abc')
print(new_li)  # ['a', 'b', 'c']
print(li)  # ['a', 'b', 'c']
print(new_li == li)  # True
print(li is new_li)  # True

可以看到原地操作符在操作可变数据类型时,会更新原数据,并且返回值是更新后的原数据。那么 t.li += 'abc' 等效于 t.li = operator.iadd(t.li, 'abc'),这样,结合赋值语句的特性,就解释了结果。

相关文章

  • 实例就地操作类属性

    Python 中,类实例可以引用类的属性,就地操作符可以就地修改一个可变对象。那么通过实例引用一个可变类型的类属性...

  • Python:borg模式

    borg是使用共享属性实现的。 这种模式下,每个实例的属性字典由类字典代理,每个实例均可操作类字典

  • Python-类和对象

    关键词:类、实例、继承、重载创建类: 创建类实例对象: 属性操作: 类的继承: 继承类定义时,括号内填写父类名称继...

  • 类6.类的实例属性

    定义 类的实例属性,就是类的实例所拥有的属性,是实例的特色之处。和类的属性的区别:类的实例属性属于这个实例所拥有,...

  • TypeScript:属性装饰器

    回顾类的属性 回顾面向对象,类中的属性分为实例属性和静态属性,实例属性属于实例化后的对象,静态属性属于类本身 在类...

  • 前端装饰器ES decorator,从原理到入门

    装饰器 添加静态属性(修饰类本身) 添加实例属性(通过 prototype 对象操作) 通过 mixins 装饰器...

  • Python类属性和实例属性

    两种属性的语法 类实例的访问 类实例可以通过类访问也可以通过实例访问 赋值操作是需要特别注意的 可以发现,当我们试...

  • Python的类属性,实例属性,类方法,实例方法,静态方法

    什么是类对象,什么是实例对象类对象: 类名就是类对象实例对象:类创建的对象 类属性,实例属性类属性: 就是类所拥有...

  • 类方法 VS 静态方法

    类对象、实例对象、类属性、实例属性、类方法、实例方法、静态方法。 @staticmethod@classmetho...

  • Python实例变量和类变量

    Python实例变量和类变量 类变量(类属性): 类变量属于类所有,所有实例共享一个变量 实例变量(实例属性) 实...

网友评论

      本文标题:实例就地操作类属性

      本文链接:https://www.haomeiwen.com/subject/kvfrlctx.html