Discuss / Python / 为什么slots里面的变量score是只读的?

为什么slots里面的变量score是只读的?

Topic source

class Stu(object):
    __slots__=('name','gender','score','nation')
    pass


def set_score(self, score):
    self.score = score
    print('you get score:',score)


will  = Stu()
Joana = Stu()

from types import MethodType
Stu.set_score = MethodType(set_score, Stu)

will.set_score(85)
print('will:',will.score)

Joana.set_score(100)
print('will:',will.score)
print('Joana',Joana.score)

will.score = 80
Joana.score = 0
print('will:',will.score)
print('Joana:',Joana.score)

运行结果: you get score: 85 will: 85 you get score: 100 will: 100 Joana 100 Traceback (most recent call last): File "work_1_16.2.py", line 29, in <module> will.score = 80

AttributeError: 'Stu' object attribute 'score' is read-only

主要看最后赋值那部分,按照上述程序,will.score和Joana.score都不能赋值,说变量score是只读的, 当我把slots那条语句注释掉后。就会有正常结果,所以,为什么slots里面的变量score是只读的?

在stackoverflow里查到一个相关问题 http://stackoverflow.com/a/5758040

根据documentation on slots : slots are implemented at the class level by creating descriptors (Implementing Descriptors) for each variable name. As a result, class attributes cannot be used to set default values for instance variables defined by slots; otherwise, the class attribute would overwrite the descriptor assignment.

slots 里的变量不能设置默认值,所以意思是说只能通过方法(如set_score)来改变变量score的值,而不能通过赋值的方式吗?

BrcNkeepSo-So

#3 Created at ... [Delete] [Delete and Lock User]

Stu.score = 999可以修改.

大概通过类方法Stu.set_score = MethodType(set_score, Stu)初始化(或修改)的成员变量变成类成员变量, 只能通过类去修改, 读不受限制

去掉slots就没有限制了,随便怎么写都不会只读.

slots里做限定的是tuple,我是这样理解的,不知道对否。也不知为啥这儿需要只读嘞。

rollingcat80

#5 Created at ... [Delete] [Delete and Lock User]

即使没有在slots里定义,只要设置default value也会变成read-only,奇怪啊.

下面jerry.grade的时候报错了。

class Human(object):
    __slots__=('name','race','gender')
    def __init__(self,name):
        self.name=name
    pass

class Student(Human):
    __slots__=('score')
    grade='A'
    def __init__(self,name):
        self.name=name   

    def print_me(self):
        print('hi %s %s:' % (self.name,self.grade))    
    pass

tom=Human('Tom')
jerry=Student('Jerry')
jerry.grade='A'

  • 1

Reply