首页 新闻 会员 周边

property和自定义描述符区别

0
[已关闭问题] 关闭于 2026-06-10 10:03
class Student():
    def __init__(self, stuid, name, score1, score2, score3):
        self.stuid = stuid
        self.name = name
        self._score1 = score1
        self._score2 = score2
        self._score3 = score3

    def get_score1(self):
        return self._score1

    def set_score1(self, score):
        if 0 <= score <= 100:
            self._score1 = score
        else:
            raise ValueError("score not in [0,100]")

    def get_score2(self):
        return self._score2

    def set_score2(self, score):
        if 0 <= score <= 100:
            self._score2 = score
        else:
            raise ValueError("score not in [0,100]")

    def get_score3(self):
        return self._score3

    def set_score3(self, score):
        if 0 <= score <= 100:
            self._score3 = score
        else:
            raise ValueError("score not in [0,100]")

    score1 = property(get_score1, set_score1)
    score2 = property(get_score2, set_score2)
    score3 = property(get_score3, set_score3)

    def returnMe(self):
        return "%s, %s, %i, %i, %i" % (
            self.stuid,
            self.name,
            self.score1,
            self.score2,
            self.score3)
和from weakref import WeakKeyDictionary

class Score():
    """ score should in [0,100] """

    def __init__(self):
        self.score = WeakKeyDictionary()
        #self.score = {}

    def __get__(self, instance, owner):
        return self.score[instance]

    def __set__(self, instance, value):
        if 0 <= value <= 100:
            self.score[instance] = value
        else:
            raise ValueError("score not in [0,100]")


class Student():
    # 托管属性定义在类级别上
    score1 = Score()
    score2 = Score()
    score3 = Score()

    def __init__(self, stuid, name, score1, score2, score3):
        self.stuid = stuid
        self.name = name
        self.score1 = score1
        self.score2 = score2
        self.score3 = score3

    def returnMe(self):
        return "%s, %s, %i, %i, %i" % (
            self.stuid,
            self.name,
            self.score1,
            self.score2,
            self.score3)


stu = Student("20101120", "malong", 67, 77, 88)
print(stu.returnMe())
stu.score1 = -23
这两个为什么第一个重复代码,第二个没重复,这两个都用了描述符,只不过第一个用了成品property,第二个是自定义描述符,那为什么第一个代码就冗余了呢
*Tesla*的主页 *Tesla* | 小虾三级 | 园豆:1762
提问于:2026-06-10 10:00
< >
分享
所有回答(1)
0
property 本质上就是 Python 内置的一种“成品”描述符,而你手写的 Score 类是“自定义”描述符。既然都是描述符,为什么第一个代码显得冗余,而第二个却很优雅呢?
 
property 确实解决了“让方法像属性一样访问”的问题,但在面对多个属性需要相同校验规则的场景时,它依然会导致样板代码泛滥。而真正的“自定义描述符”通过面向对象的思想,将这种通用规则彻底抽离,实现了真正的代码复用。这也是为什么 Django、SQLAlchemy 等高级框架底层都大量使用自定义描述符的原因。
  • property 只是一个“外壳”,它本身不知道你要验证什么。所以每次用它,你都得把具体的验证逻辑(如分数范围检查)塞进它的肚子里。要管3个分数,就得塞3次。
  • 自定义描述符 (Score) 是一个自带逻辑的“独立个体”。你把验证逻辑写在了它自己的类定义里。以后无论有多少个属性需要这个规则,都只需要实例化(调用)它就行了。
简单来说:property 让你复用了一种“访问属性的方式”,而自定义描述符让你直接复用了“业务逻辑本身”。
如果把这两种做法比作工厂生产零件:
  • 第一种(property):相当于你有一个通用的模具(property),但每次生产新零件(score2),你都要亲自手工雕刻一遍花纹(重复写 if 0 <= value <= 100)。
  • 第二种(自定义描述符):相当于你直接做了一个带有特定花纹的专用模具(Score 类)。以后不管生产多少个同类零件,直接拿这个模具一压就行了。
*Tesla* | 园豆:1762 (小虾三级) | 2026-06-10 10:03
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册