Python Class笔记2:属性的__slots__和@property方法

1. __slots__ : 申明允许赋予给实例的属性

Python默认用字典__dict__来保存类的实例属性,这会占用大量的空间。
使用__slots__后,Python不会再建立字典,只给一个slots声明的属性分配空间。
当一个类需要创建大量实例时,可以通过__slots__声明实例所需要的属性,以减小内存占用。

1.1 先看看没有__slots__的情况

class Teacher(object):
    def __init__(self, name='saolaoshi', age=21, number='158xxxx1234'):
        self.name = name
        self.age = age
        self.number = number
    
    def say_hello(self):
        print('hello', name, '!')

# 创建实例sls
sls = Teacher(name='saolaoshi')
# 打印sls的属性
print(sls.__dict__)

运行结果:
{‘name’: ‘saolaoshi’, ‘age’: 21, ‘number’: ‘158xxxx1234’}

我们给sls添加一些新的属性

sls.hair_curl = 'permanent wave'
sls.hair_color = 'darkblue'
# 再打印结果
print(sls.__dict__)

运行结果:
{‘name’: ‘saolaoshi’, ‘age’: 21, ‘number’: ‘158xxxx1234’, ‘hair_curl’: ‘permanent wave’, ‘hair_color’: ‘darkblue’}

看,还是可以绑新的属性给sls的。

1.2 加入__slots__

class Teacher(object):
    __slots__ = ('name', 'age', 'number', 'hair_color')
    def __init__(self, name='saolaoshi', age=21, number='158xxxx1234'):
        self.name = name
        self.age = age
        self.number = number
    
    def say_hello(self):
        print('hello', name, '!')

sls = Teacher()        
print(sls.__dict__) # 结果1
sls.hair_color = 'darkblue'		 # 结果2
sls.hair_curl = 'permanent wave' # 结果2

运行结果:

  1. 确实,有__slots__无__dict__。在这里插入图片描述2. 只能添加hair_color属性,没有hair_curl属性。在这里插入图片描述

2 @property:属性校验

对于Teacher()类,我们希望属性name的type为str,age为 0~100 的int。
在建立每一个实例的时候,都应该对属性进行校验,合格则允许创建,不合格则进行提示。

2.1 用描述符__get__和__set__以及__delete__

  • __get__():调用一个属性时,触发
  • __set__():为一个属性赋值时,触发
  • __delete__():采用del删除属性时,触发

还是以Teacher类为例:

"""定义一个Teacher类,假设它只有一个属性name,而name用包含描述符的Name类代理"""
class Name:
    def __get__(self, instance, owner):
        print('调用属性')
        print(instance, '\n', owner)
    
    def __set__(self, instance, value):
        print('设置属性')
        print(instance, '\n', value)
        
    def __delete__(self, instance):
        print('删除属性')
        print(instance)
        
class Teacher(object):
    name = Name() # 这时候,name属性由Name类来代理
    
    def __init__(self, name):
        self.name = name
      
"""进行三次测试"""         
sls = Teacher(name='saolaoshi')  # 结果1
sls.name						 # 结果2
del sls.name					 # 结果3

运行结果:

  1. 设置属性
    <__main__.Teacher object at 0x7feff1332550>
    saolaoshi
  2. 调用属性
    <__main__.Teacher object at 0x7feff1332550>
    <class ‘__main__.Teacher’>
  3. 删除属性
    <__main__.Teacher object at 0x7feff1332550>

2.2 用@property装饰器

@property的作用是:把方法变成属性调用,保证对参数进行必要的检查

还是比如,我们有一个Teacher类,在里面要保证name是str

class Teacher(object):
    def __init__(self, name='Youlaoshi', age='21'):
        self._name = name  # 注意:self的属性是_name,成员方法是name()
        self.age = age
    
    # 读取传进来的参数name,相当于__get__
    @property
    def name(self):
        print('读取')
        print(self._name)
        return self._name
    
    # 进行设置,相当于__set__
    @name.setter
    def name(self, value):
        print('设置')
        print(value)
        if isinstance(value, str):
            self._name = value
        else:
            raise ValueError("'str' type needed")
    
    # 进行删除,相当于__delete__
    @name.deleter
    def name(self):
        print('删除')
        del self._name
    
sls = Teacher()

"""进行三次测试"""
sls.name				# 结果1
sls.name = 'Saolaoshi'  # 结果2
del sls.name			# 结果3

运行结果

  1. 读取
    Youlaoshi
  2. 设置
    Saolaoshi
  3. 删除

注意:

  1. 在最开始init的时候,self的属性名是_name,方法名是name()
  2. 当我们在外部对属性进行操作的时候,是调用的name方法名进行操作,而非属性
  3. @property需要在@x.setter和@x.deleter前面,只有@property的时候是只读属性

:若在使用的时候忘记了语法,可以help(property)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值