aifadian 2025-12-08 17:49 采纳率: 0%
浏览 4

以下代码通过描述符协议实现了一个属性验证器。当 `d.value = -10` 这行代码被执行时,程序会发生什么?

以下代码通过描述符协议实现了一个属性验证器。当 d.value = -10 这行代码被执行时,程序会发生什么?

class NonNegative:

    def __set_name__(self, owner, name):
        self.private_name = '_' + name
    def __get__(self, instance, owner):
        return getattr(instance, self.private_name)
    def __set__(self, instance, value):
        if value < 0:
            raise ValueError("Negative value not allowed")
        setattr(instance, self.private_name, value)
class Data:
    value = NonNegative()
    def __init__(self, value):
        self.value = value
d = Data(10)

  • 写回答

3条回答 默认 最新

  • 檀越@新空间 2025-12-08 17:59
    关注

    下午好🌅🌅🌅
    本答案参考通义千问

    当执行 d.value = -10 这行代码时,程序会根据描述符协议(descriptor protocol)的机制进行处理。由于 Data.value 是一个 NonNegative 类型的实例,它是一个描述符,因此在对 d.value 赋值时,会调用 NonNegative.__set__() 方法。


    具体流程分析:

    1. 赋值操作触发描述符的 __set__ 方法
      当执行 d.value = -10 时,Python 会检测到 value 是一个描述符(即 NonNegative 实例),因此会调用该描述符的 __set__ 方法。

    2. __set__ 方法检查值是否为负数
      NonNegative.__set__ 中,会判断传入的 value 是否小于 0。如果小于 0,会抛出 ValueError("Negative value not allowed") 异常。

    3. 异常被抛出,程序中断
      因为 value = -10 是一个负数,所以 __set__ 方法会抛出异常,导致程序停止执行,并显示错误信息。


    最终结果:

    • 程序会抛出以下异常:
    ValueError: Negative value not allowed
    
    • d.value 的值不会被设置为 -10,因为赋值操作在 __set__ 方法中被阻止了。

    解决方案:

    如果你希望允许赋值为负数,或者需要更灵活的验证逻辑,可以修改 NonNegative.__set__ 方法,例如添加条件判断或日志记录。以下是修改后的代码示例:

    class NonNegative:
        def __set_name__(self, owner, name):
            self.private_name = '_' + name
    
        def __get__(self, instance, owner):
            return getattr(instance, self.private_name)
    
        def __set__(self, instance, value):
            if value < 0:
                print(f"Warning: Negative value {value} is not allowed.")
                # 或者选择忽略错误,不抛出异常
                # raise ValueError("Negative value not allowed")
            setattr(instance, self.private_name, value)
    
    class Data:
        value = NonNegative()
    
        def __init__(self, value):
            self.value = value
    
    d = Data(10)
    d.value = -10  # 此时不会抛出异常,仅打印警告
    

    总结:

    • 执行 d.value = -10 会触发 NonNegative.__set__ 方法。
    • 由于值为负数,__set__ 方法会抛出 ValueError("Negative value not allowed")
    • 如果你想避免异常,可以修改 __set__ 方法的逻辑,如添加日志、忽略错误等。
    评论

报告相同问题?

问题事件

  • 创建了问题 12月8日