属性的正确使用方法

Correct way to use properties

我的属性getter/setters之前

class Child(Base):
    @property
    def prop(self) -> Optional[int]:
        """Doc"""
        return getattr(self, "_prop", None)

    @prop.setter
    def prop(self, value: int):
        self._set("prop", value)   # where _set itself is a method to reduce boilerplate

现在,

prop = Prop.int_prop("prop", "Doc")

其中 Prop.int_prop 看起来像这样:

@staticmethod
def int_prop(name: str, doc: str) -> property:
    def fget(self: Base) -> Optional[int]:
        return getattr(self, "_" + name, None)
    
    def fset(self: Base, value: int) -> None:
        self._set(name, value)
    
    return property(fget, fset, doc=doc)

编辑:_set 方法

# Dump value to event store if event exists
event = self._events.get(name)
if event:
   logger.info(f"Dumping value {value} to {repr(event)}")
   event.dump(value)

# Assign value to local variable
setattr(self, "_" + name, value)

一方面,这让我感到自豪,因为我正在从事的项目中有近 70% 是 属性 getters/setters。虽然我同意上面的方法更 Pythonic 和干净,下面的方法减少了很多代码。但是,它剥夺了 VS Code 在 属性 名称下方显示文档字符串的能力。

是否有解决此问题的方法或总体上更好的方法?

除非 VS Code 支持 PEP-257 的属性文档字符串定义,否则这只能被视为扩展注释而不是正确答案。我从未使用过 VS Code,无法测试它对此的支持。

在防御中,它在语法上提供文档字符串,而不是在运行时动态设置 __doc__ 属性,因此它有机会解决问题中提出的主要问题。


如果我关心IDE支持,我会写一个自定义描述符并遵循属性文档字符串的PEP-257指南。

# Adapted from examples in https://docs.python.org/3/howto/descriptor.html
class IntPropety:
    def __set_name__(self, owner, name):
        self.public_name = name
        self.private_name = "_" + name

    def __get__(self, obj, objtype=None) -> Optional[int]:
        if obj is None:
            return self
        return getattr(obj, self.private_name)

    def __set__(self, obj, value):
        event = obj._events.get(self.public_name)
        if event:
            logger.info(f"Dumping value {value} to {repr(event)}")
            event.dump(value)

        setattr(obj, self.private_name, value)

    

class Child(Base):
    prop = IntProperty()
    """Doc"""