码迷,mamicode.com
首页 > 其他好文 > 详细

实例属性和类属性

时间:2016-07-31 01:43:53      阅读:146      评论:0      收藏:0      [点我收藏+]

标签:

 

实例属性通过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!

实例属性和类属性

标签:

原文地址:http://www.cnblogs.com/huangxm/p/5722142.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!