1.如何限制python类的实例随意增加属性

本文探讨了如何限制Python类实例随意增加属性,并确保变量值在特定范围内。通过使用`__slots__`和`@property`装饰器,可以限制实例属性并控制变量赋值。同时,介绍了`__setattr__`内建函数的作用,防止访问不存在的属性。文章还分析了`__dict__`和`__slots__`的区别,强调了内存优化的重要性。最后,展示了`dir()`和`__dict__`在类和实例中的应用,揭示了它们在追踪实例属性时的角色。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

某公司一面中给出一段代码:

class Student():
    def __init__(self, name):
        print "Student inti"
        super(Student, self).__init__(name)
if __name__ == "__main__":
    s1 = Student("XIAOMIN")
    s1.english =90

要求可以使用s1.english =90的方式直接访问变量,但是需要对变量值做限制(0-100间的整数);又要防止输入错误添加新的不合法的变量进去(如english 错误的写为englash ),如何实现?

 

答案:使用__slots__进行变量限制,使用装饰器@property进行变量控制:

# coding=utf-8
__author__ = 'Wang'

class Person(object):
    __slots__ = ('_name', '_age', '_sex') ##限制基类变量只能有这三个属性,实例对象无法增加新的属性,这就防止了用户误输入

    def __init__(self, name):
        self._name = name
        print "Person init"

class Student(Person):
    __slots__ = ('_grade', '_english', '_chinese')##限制基类变量只能有这三个属性,实例对象无法增加新的属性,这就防止了用户误输入

    def __init__(self, name):
        print "Student inti"
        # Person.__init__(self, name)
        super(Student, self).__init__(name)

    @property                         ##property 方法访问变量
    def english(self):
        return self._english

    @english.setter                  ##property 方法设置变量,这里面对参数进行了校验
    def english(self, value):
        if not isinstance(value, int):
            raise ValueError('分数必须是整数才行呐')
        if value < 0 or value > 100:
            raise ValueError('分数必须0-100之间')
        self._english = value


if __name__ == "__main__":
    s1 = Student("XIAOMIN")
    s1._english =90     ####正常执行,不使用装饰器直接设置变量
    s1.english =90      ####正常执行,使用装饰器直接设置变量
    s1.englash =90   ####不能正常执行,AttributeError: 'Student' object has no attribute 'englash'
    s1._englash =90   ####不能正常执行,AttributeError: 'Student' object has no attribute '_englash
    s1._english =90.5  ####正常执行,不使用装饰器直接设置变量可以设置成浮点数
    s1.english =90.5   #####不能正常执行,引发ValueError

另外可以使用内建函数__setattr__来对变量赋值   

    s1.__setattr__('_english', 90)  ###直接访问变量,没有经过装饰器函数
     s1.__setattr__('english', 90.5) ###执行失败,经过装饰器函数校验
    print s1.__getattribute__('_english')
    s1.__setattr__('_englaash', 90)   #####不能正常执行,AttributeError

知识点1:

1) __slots__限制实例随意增加属性,而__setattr__内建函数则不允许访问不存在的属性

2) __slots__使对__dict__的替代,存在__slots__的类不存在__dict__,访问是s1.__dict__会引发AttributeError

3)执行vars(s1)会引发TypeError,vars()内建函数与dir()类似,但是必须要求实例中包含__dict__

4) __dict__属性跟踪所有的实例属性,返回的是一个字典,占用内存较多,基于内存考虑的话可以用__slots__代替__dict__

知识点2:

看一下实例和变量的__dict__属性,包含哪些内容:

class anmon(object):
    '''
    this is doc.
    '''

    def __init__(self, name):
        self._name = name
        print "anmon init"

    def anon_a(self):
        self.anon_a = 'aaaa'
if __name__ == "__main__":
    print anmon.__dict__
    a2 = anmon('xiaoli')
    print a2.__dict__
    a2.anon_a()
    print a2.__dict__

{'__module__': '__main__', 'anon_a': <function anon_a at 0x0000000002DC9048>, '__dict__': <attribute '__dict__' of 'anmon' objects>, '__weakref__': <attribute '__weakref__' of 'anmon' objects>, '__doc__': '\n    this is doc.\n    ', '__init__': <function __init__ at 0x0000000002DC3F98>}
anmon init
{'_name': 'xiaoli'}    #####print a2.__dict__
{'anon_a': 'aaaa', '_name': 'xiaoli'}   #####执行完anon_a()再次执行print a2.__dict__多了一个变量

知识点3:

使用dir查看类和实例

class anmon(object):
    '''
    this is doc.
    '''

    def __init__(self, name):
        self._name = name
        print "anmon init"

    def anon_a(self):
        self.anon_a = 'aaaa'

if __name__ == "__main__":

    a2 = anmon('xiaoli')
    print dir(anmon)
    print dir(a2)

['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'anon']


['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_name', 'anon']

1)都包含了内建函数、内建属性和定义的方法名称
2)实例的dir中多了init中定义的变量_name,但不包含普通方法中定义的anon_a

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值