Python中@property与@propertyName.setter等装饰器的用法有什么区别?
结论
你贴出的第二种写法本身存在语法错误,正常环境下根本无法运行,你测试时能得到和第一种写法一致的结果,大概率是实际运行的代码和你贴的示例不一致,比如提前在外部定义过propertyName、playingField两个对象才没有触发报错。
两种写法的核心差异
第一种是Python官方标准的property定义写法,逻辑完全自洽
class ClassName(): def __init__(self, xSize: int, ySize: int): self.xSize: int = xSize self.ySize: int = ySize @property def propertyName(self): return self._propertyName @propertyName.setter def propertyName(self, field: list): self._propertyName = field
它的运行逻辑是:
- 先用
@property装饰getter方法,这一步会自动把被装饰的方法包装成一个property类型的对象,赋值给当前类的同名类变量ClassName.propertyName - 再用
@propertyName.setter装饰setter方法,本质是调用已经生成的propertyName对象的setter方法,把新的方法绑定为该property的写入逻辑,再重新赋值回ClassName.propertyName。
最终你访问实例的propertyName属性时,就会自动触发对应的读写逻辑。
第二种写法存在明显的作用域错误
class ClassName(): def __init__(self, xSize: int, ySize: int): self.xSize: int = xSize self.ySize: int = ySize @propertyName.getter def propertyName(self): return self._propertyName @playingField.setter def playingField(self, field: list): self._propertyName = field
Python解释器在执行类内部的装饰器代码时,会按从上到下的顺序执行:
- 执行到
@propertyName.getter这一行时,当前类作用域里还没有定义propertyName这个变量,直接会抛出NameError: name 'propertyName' is not defined异常,代码根本无法完成类的定义。 - 就算你在类的外部提前定义过
propertyName,后面的@playingField.setter也会触发同样的NameError,就算你也定义了全局的playingField,这个setter绑定的也是全局对象,和当前类的propertyName属性没有任何关联,不可能实现和第一种写法一致的效果。
补充说明
如果你是写示例时手滑打错了变量名,实际是先通过@property定义了property对象,之后再用@xxx.getter/@xxx.setter重写对应的读写方法,这种场景下两种写法的运行效果确实是一致的。不过这种写法通常只用在需要修改已有property的读写逻辑的场景,常规定义property的时候不需要这么写。
内容的提问来源于stack exchange,提问作者Swayment
相关产品推荐
相关产品推荐

