Discuss / Python / 抛砖引玉,粗略实现property

抛砖引玉,粗略实现property

Topic source

掠刎

#1 Created at ... [Delete] [Delete and Lock User]
class Property:
    def __init__(self, func_get):
        self.func_get = func_get#保存所装饰的获取属性的函数
        self.func_set = None

    def setter(self, func_set):
        self.func_set = func_set#保存所装饰的设置属性的函数
        return self

    def __get__(self, instance, owner): #在获取值时调用,如print(s.score)
        return self.func_get(instance)

    def __set__(self, instance, value):#在设置值时调用,如s.score = 90
        if self.func_set:#如果self.func_set被设置了,即用setter装饰过
            self.func_set(instance, value)
        else:#否则表示这是一个只读对象
            raise AttributeError("can't set attribute")

#----------------------------------测试property-----------------------------------
class Student:
    def __init__(self, value):
        self._score = value
    @Property
    def score(self):
        return self._score
#上面等价于score = Property(score) 即装饰之后score就是一个Property的实例了,我们在用score的时候实际是在用一个Property对象
    @score.setter   #这里的score就是上面的score
    def score(self, value): #这个是新定义的score,给它取个别名叫set_score,实际上这个函数定义可以改成set_score或你想要的名字
        # 我觉得命名为set_score更好一点
        if not isinstance(value, int):
            raise ValueError("score必须是整数")
        if value>100 or value<0:
            raise ValueError("score数值有误")
        self._score = value
#上面等价于score = score.setter(set_score),由于setter 中 return self,所以这里的score仍然是那个Property对象

s = Student(60)
print(s.score)
s.score = 90
print(s.score)
try:
    s.score = "a"   #score必须是整数
except BaseException as e :
    print(e)
try:
    s.score = 101   #score数值有误
except BaseException as e :
    print(e)

#----------------------只读测试-------------------
class Student2:
    def __init__(self, value):
        self._score = value
    @Property
    def score(self):
        return self._score

s2 = Student2(60)
print(s2.score)
try:
    s2.score = 0    #can't set attribute
except BaseException as e :
    print(e)

粗略的实现了一下property装饰器,这个过程也让自己对property以及装饰器的理解更深了一层,便分享出来,以抛砖引玉,若能帮到部分新手,甚妙哉。当然我自己也是一个初学者,水平有限,如有不正确的地方欢迎指正。

注:python自带的property是小写,我这里用的Property是首字母大写

掠刎

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

补充:我这里的Property的实现能给setter装饰的函数取其它名字,如

@score.setter  
def score(self, value):

可以改成

@score.setter  
def set_score(self, value):

但python自带的property的setter是不能改名字的,也就是上面的代码只能用score 特此说明以免误导

虽然看不太懂,还是点个赞,你这是新手么......

请问python自带的property为什么要加_ 比如必须写成self.width,不加就会报错


  • 1

Reply