zoukankan      html  css  js  c++  java
  • 实例属性和类属性

    实例属性通过self或实例变量来定义,注意__init__方法中定义的是实例属性:

    class Student(object):
        def __init__(self, name):
            self.name = name
    
    s1 = Student('Bob')
    #给实例添加一个属性
    s1.score = 90
    
    s2 = Student('Jim')

    在实例s1中添加一个属性score, 该属性只对s1有用,在s2中是没有的:

    >>> s1.score
    90
    >>> s2.score
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    AttributeError: 'Student' object has no attribute 'score'

    类属性是怎么定义的呢?

    class Student(object):
        name = 'Student'

    当我们定义一个类属性后,这个属性归类所有,所有的实例都可以访问它:

    >>> s1 = Student()
    >>> s2 = Student()
    >>> s1.name, s2.name
    ('Student', 'Student')

    现在修改一个s1的name, 会出现什么情况呢?

    >>> s1.name = 'windows'
    >>> s1.name
    'windows'
    >>> s2.name
    'Student'

    再删除s1的那么属性:

    >>> del s1.name
    >>> s1.name
    'Student'

    也可以删除类的属性,类属性删除后,所有实例都将不能访问该属性了:

    >>> del Student.name
    >>> s1.name
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    AttributeError: 'Student' object has no attribute 'name'
    >>> s2.name
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    AttributeError: 'Student' object has no attribute 'name'

    同样的,也可以给实例和类绑定一个方法:

    class Student(object):
        pass
    
    def set_age(self, age): # 定义一个函数作为实例方法
         self.age = age
    
    >>> s = Student()
    >>> from types import MethodType
    >>> s.set_age = MethodType(set_age, s) # 给实例绑定一个方法
    >>> s.set_age(25) # 调用实例方法
    >>> s.age # 测试结果
    25

    给实例绑定的方法,对另一个实例是不生效的;如果要给所有实例绑定方法,可以在类上绑定:

    def set_score(self, score):
        self.score = score
    
    Student.set_score = set_score

    给类绑定方法后,所有的实例都可以访问;一般情况下,方法可以直接写在类中,但动态绑定允许程序在运行过程中动态添加功能。

    但有时候我们不希望对实例随意添加属性或方法,比如我们希望只允许对实例添加age和name属性;Python允许在定义class的时候,定义一个特殊的__slots__变量,来限制该class实例能添加的属性:

    class Student(object):
        __slots__ = ('name', 'age') # 用tuple定义允许绑定的属性名称

    但要注意的是,__slots__只对当前类实例起作用,对子类是不起作用的;除非在子类中也定义__slots__; 这样子类允许定义的属性就是子类__slots__ + 父类__slots__


    如果在Student类中有个score属性,那么通过Student.score来访问的时候,就暴露了score属性;知道了score属性,就可以随意对它进行修改,而且不能进行正确性检测,比如把成绩修改成abc,显然是不合适的,要解决这个问题,可以设置一个方法get_score()来获取成绩, set_score()来设置成绩:

    class Student(object):
    
        def get_score(self):
             return self._score
    
        def set_score(self, value):
            if not isinstance(value, int):
                raise ValueError('score must be an integer!')
            if value < 0 or value > 100:
                raise ValueError('score must between 0 ~ 100!')
            self._score = value

    那有没有办法通过Student.score来访问,又有正确性检测呢?  那就需要用到@property装饰器,来把方法变成属性:

    class Student(object):
    
        @property
        def score(self):
            return self._score
    
        @score.setter
        def score(self, value):
            if not isinstance(value, int):
                raise ValueError('score must be an integer!')
            if value < 0 or value > 100:
                raise ValueError('score must between 0 ~ 100!')
            self._score = value

    这样就可以像属性一样操作了:

    >>> s = Student()
    >>> s.score = 60 # OK,实际转化为s.set_score(60)
    >>> s.score # OK,实际转化为s.get_score()
    60
    >>> s.score = 9999
    Traceback (most recent call last):
      ...
    ValueError: score must between 0 ~ 100!
  • 相关阅读:
    python opencv PyQt5
    各大web服务器https的证书文件
    mysql 常用字符串操作
    python 修改字符串中的某一位字符
    python mysql
    小程序
    m4a 转MP3
    安装python 3.7
    树莓派版本信息
    bash 重启后台程序脚本
  • 原文地址:https://www.cnblogs.com/huangxm/p/5722142.html
Copyright © 2011-2022 走看看