属性操作

Python 是动态语言,对象的属性不仅可以查看、访问、调用,还可以动态地增、删、改。

下面定义一个没有自定义属性的类 A 举例:

dir() 函数查看属性,双下划线 __ 包围的属性是继承自 object 的特殊属性:

# 定义一个类,查看属性
class A:
    pass

dir(A)
['__class__',
 '__delattr__',
 '__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__']
# 访问属性 __class__ 相当于调用 type() 函数
A.__class__, A().__class__
(type, __main__.A)

给类 A 及其实例动态添加属性,属性可以是数据属性和方法。类层级添加的属性,将作为所有实例的属性;实例添加的属性,只有对应的实例能访问。

# 添加数据属性
a1 = A()
a2 = A()
A.a = '类变量'
a1.x = 'a1 的属性'
a2.y = 'a2 的属性'
# 类层级添加方法
def f(self):
    print(self.a)

A.f = f
# 类 A 调用刚添加的属性
A.f(a1)
A.f(a2)
类变量
类变量
# 实例调用刚添加的属性
a1.f()
a2.f()
类变量
类变量
# 实例 a1 没有 y 属性
# 同理,a2 没有 x 属性
a1.y 
---------------------------------------------------------------------------

AttributeError                            Traceback (most recent call last)

<ipython-input-44-178a7ac627a0> in <module>
      1 # 实例 a1 没有 y 属性
      2 # 同理,a2 没有 x 属性
----> 3 a1.y


AttributeError: 'A' object has no attribute 'y'

实例直接添加一个函数作为属性,将不会隐式地将自身作为第一个参数,而是和正常函数一样使用:

def p(self):
    print(self)

a1.p = p
a1.p('正常传参')
a1.p()
正常传参


---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

<ipython-input-45-4ebdece61250> in <module>
      4 a1.p = p
      5 a1.p('正常传参')
----> 6 a1.p()


TypeError: p() missing 1 required positional argument: 'self'

如果要通过实例添加实例方法(第一个参数 self 即是自身的方法),可以通过 types 模块添加。添加的属性,类不可访问,只有对应的实例可访问:

from types import MethodType

# 改变了 a1 的上述 p 属性
a1.p = MethodType(p, a1)
a1.p()
<__main__.A object at 0x000001D40578D730>
A.p
---------------------------------------------------------------------------

AttributeError                            Traceback (most recent call last)

<ipython-input-47-94cb580acfb0> in <module>
----> 1 A.p


AttributeError: type object 'A' has no attribute 'p'
a2.p
---------------------------------------------------------------------------

AttributeError                            Traceback (most recent call last)

<ipython-input-48-29321b2aa581> in <module>
----> 1 a2.p


AttributeError: 'A' object has no attribute 'p'

删除属性使用 del 语句:

del a1.p

a1.p()
---------------------------------------------------------------------------

AttributeError                            Traceback (most recent call last)

<ipython-input-49-9cf9b7e7dc86> in <module>
      1 del a1.p
      2 
----> 3 a1.p()


AttributeError: 'A' object has no attribute 'p'