Python 有时是只读属性

Python 有时是只读属性,python,python-2.7,properties,setter,Python,Python 2.7,Properties,Setter,我有一个类,CameraInterface,具有两个属性: 录制(布尔值) 记录质量(具有三个可能值的枚举) 用户可以按硬件按钮(这是一个Raspberry Pi项目)选择录制质量,但如果相机已经录制,硬件将闪烁/buzz/否则表明您在录制时无法更改录制质量 我希望CameraInterface对象强制执行此要求。我不希望future me能够忘记这一要求,并且在没有首先确保录制为False的情况下,不小心尝试设置录制质量。做这件事最像蟒蛇的方式是什么 我最熟悉Objective-C,在这里

我有一个类,
CameraInterface
,具有两个属性:

  • 录制
    (布尔值)
  • 记录质量
    (具有三个可能值的枚举)
用户可以按硬件按钮(这是一个Raspberry Pi项目)选择
录制质量
,但如果相机已经
录制
,硬件将闪烁/buzz/否则表明您在录制时无法更改
录制质量

我希望
CameraInterface
对象强制执行此要求。我不希望future me能够忘记这一要求,并且在没有首先确保
录制为False的情况下,不小心尝试设置
录制质量
。做这件事最像蟒蛇的方式是什么

我最熟悉Objective-C,在这里我可以尝试将属性外部设置为只读,然后执行以下操作:

camera = CameraInterface()
camera.recording_quality = HD
camera.start_recording()
camera.recording_quality = SD # Exception!
-(无效)设置质量:(质量)质量
successHandler:(void(^)(void))successHandler
failureHandler:(void(^)(void))failureHandler
{
如果(自记录){
if(故障处理程序){
failureHandler();
}
}
否则{
self.quality=quality;//内部可写
if(successHandler){
successHandler();
}
}
}
更新

关于我要找的东西的澄清:

  • 如果可能的话,我希望避免对控制流使用异常
  • 我想在
    CameraInterface
    的编程接口中建立
    录制质量的有时可设置的特性,这样您就不必等到运行时才发现自己做错了什么
  • 我已经知道Python属性了。我只是在寻找使用它们的最佳方法(或替代方法)
  • 更新2

    我被说服使用运行时异常,并在尝试设置
    录制质量时使用try/catch。说服我的部分原因是我试图用Python实现我的Objective-C示例。通过这样做,我意识到它确实更适合静态类型语言。让我信服的部分原因是Martijn答案中链接的答案,该答案更详细地解释了异常是Python控制流中非常正常的一部分

    这是上面Objective-C示例的Python版本。我把它放在这里作为对其他人的警告:

    导入类型
    类CameraInterface(对象):
    定义初始化(自):
    自我记录质量=1
    自我记录=错误
    @财产
    def记录质量(自我):
    返回自我。\u记录\u质量
    def设置记录质量(自我、质量、成功处理程序、失败处理程序):
    如果type(success\u handler)不是types.FunctionType:
    raise VALUERROR(“您必须传递有效的成功处理程序”)
    如果类型(故障处理程序)不是类型。函数类型:
    raise VALUERROR(“您必须传递有效的故障处理程序”)
    如果self.recording为True:
    #拒绝该设置,并调用故障处理程序
    失败处理程序()
    其他:
    自我记录质量=质量
    success_handler()
    def success():
    打印“成功设置”
    def failure():
    打印“正在录制,因此无法设置质量”
    摄像头=摄像头接口()
    打印“从{0}开始的录制质量”。格式(照相机。录制质量)
    摄像机。设置录制质量(3,成功,失败)
    摄像机记录=真
    摄像机。设置录制质量(2,成功,失败)
    
    这张照片是:

    从1开始记录质量
    成功设置
    这是录音,所以我们无法设置质量
    
    您可以使用其setter引发异常的:

    class CameraInterface(object):
        @property
        def recording_quality(self):
            return self._quality
    
        @recording_quality.setter
        def recording_quality(self, quality):
            if self.recording:
                raise CurrentlyRecordingError()
            self._quality = quality
    
    其中,
    CurrentlyRecordingError
    是一个自定义异常;它可能是的一个子类

    在Python中,使用异常是处理在特定情况下无法设置的属性的最自然的方法。也看到

    另一种方法是使用一种方法,每次您想要设置质量值时,都必须显式地测试相机录制状态。这会使API复杂化,并且很容易导致比赛条件,即在测试状态之后但在更改质量设置之前,摄像机开始录制

    除了你之外;这简化了对象的使用,因为您假定可以进行质量设置,并且可以在异常处理程序中处理只读情况

    从Python的角度(除了不使用属性之外)进一步说明您的Objective-C版本:

    • 当您可以使用时,不要使用
      type(..)是[not]typeobj
    • 而不是测试
      类型;函数不是唯一的可调用函数
    • 在Python中,您信任API的用户;如果它们传入了无法调用的内容,这是它们自己的错,并且您的对象不需要在此进行显式类型检查。Python是一种供成年人使用的语言
    • if
      语句已经测试了真实性;使用
      是正确的
      不仅是多余的,而且在与其他比较运算符一起使用时会导致难以调试的错误,因为这些运算符是链接的
      value==someothervalue为真
      并不是您认为它的意思
    您可以使用其setter引发异常的:

    class CameraInterface(object):
        @property
        def recording_quality(self):
            return self._quality
    
        @recording_quality.setter
        def recording_quality(self, quality):
            if self.recording:
                raise CurrentlyRecordingError()
            self._quality = quality
    
    其中,
    CurrentlyRecordingError
    是一个自定义异常;它可能是的一个子类

    在Python中,使用异常是处理在特定情况下无法设置的属性的最自然的方法。也看到

    另一种方法是使用一种方法,在这种方法中,您必须在每次想要录制时显式地测试相机录制状态
    camera = CameraInterface()
    camera.recording_quality = HD
    camera.start_recording()
    camera.recording_quality = SD # Exception!