20221008 python的类

类属性与实例属性

class C1 :
	x = 3 # 类属性
	def __init__(self, y=2):
		self.y = 2 # 实例属性

调用C1.__dict__ 将返回类的属性,类的属性包括描述符对象(如函数)或者任何普通数据对象,其返回值为

mappingproxy({'__module__': '__main__',
              'x': 3,
              '__init__': <function __main__.C1.__init__(self, y=2)>,
              '__dict__': <attribute '__dict__' of 'C1' objects>,
              '__weakref__': <attribute '__weakref__' of 'C1' objects>,
              '__doc__': None})

创建类的实例c, 同样调用c.__dict__,其返回值为

{'y': 2}

类属性可以在类体之外定义,对上述的C1类


C1.z = 23

C1.__dict__
Out[14]: 
mappingproxy({'__module__': '__main__',
             'x': 3,
             '__init__': <function __main__.C1.__init__(self, y=2)>,
             '__dict__': <attribute '__dict__' of 'C1' objects>,
             '__weakref__': <attribute '__weakref__' of 'C1' objects>,
             '__doc__': None,
             'z': 23}) # 类中增加z属性

对于包含在类体中的属性,引用类的属性时可以使用简单名称,而在类的方法中需要引用类的属性时,则需要使用完整名称。如下:

 class C1 :
    x = 3 # 类属性
    z = x + 3 
    def __init__(self, y=2):
        f = C1.x + 3
        self.y = 2 # 实例属性

当在__init__中使用简单名称时,会报错如下:

class C1 :
    x = 3 # 类属性
    z = C1.x + 3 
    def __init__(self, y=2):
        f = x + 3
        self.y = 2 # 实例属性
        

x = C1()

Traceback (most recent call last):

  File "<ipython-input-24-d2acc31e39c1>", line 1, in <module>
    x = C1()

  File "<ipython-input-23-c9b9efa33951>", line 5, in __init__
    f = x + 3

NameError: name 'x' is not defined

属性的引用

引用类的属性

C1.x

  1. 当x是类C1.__dict__ 中的键时, 从C1.__dict__中提取值v。如果v是一个描述器,则C1.x的值是调用type(v).__get__(v,None,C)的结果,否则,C1.x的值为v
  2. 否则,在基类中查找。

引用实例的属性

c = C1() , 引用实例c的属性y时,遵循如下的查找顺序

  1. 如果y是一个数据描述器v,则c.y 的返回值为type(v).__get__(v,x,C1)
  2. 如果y在c.__dict__中,则返回c.__dict__['y']的值
  3. 否则,在基类中查找

描述器的概念:
描述器是实现了__get____set____delete__三个任意一个方法的类。
如果一个类仅仅实现了__get__()方法,称为非数据描述器non-data descriptor;
如果一个类实现了__get__()__set__()方法,称为数据描述器data descriptor;

__slots__方法

python中,对类C的一个实例c, 存在c.__dict__, 通过这个字典,可以将任意属性绑定到实例c上。

class C1 :
    x = 3 # 类属性
    y = 2 
    def __init__(self):
        self.z = 3
        

c = C1()

c.m=2

c.__dict__
Out[57]: {'z': 3, 'm': 2}

即没有在实例c可以拥有没有在类C中定义的属性。而通过指定__slots__方法,实例c将不含有__dict__属性, 试图在实例上绑定不在__slots__中的属性将会引发异常。

class C1 :
    __slots__ = "z"
    x = 3 # 类属性
    y = 2 
    def __init__(self):
        self.z = 3
        

c = C1()

c.__dict__
"""
Traceback (most recent call last):

  File "<ipython-input-60-dac4a86e0bb3>", line 1, in <module>
    c.__dict__

AttributeError: 'C1' object has no attribute '__dict__'
"""

c.m = 2
"""
Traceback (most recent call last):

  File "<ipython-input-61-226b97bd737b>", line 1, in <module>
    c.m = 2
"""

参考

  1. 全面解析python类的绑定方法与非绑定方法
  2. Python技术手册(第2版)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值