My property getter/setters before
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
Now,
prop = Prop.int_prop("prop", "Doc")
where Prop.int_prop
looks like this:
@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)
EDIT: _set
method
# 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)
On one hand this makes me feel proud, because close to 70% of the project I am working on is the property getters/setters. While I agree the above method is more Pythonic and clean, the method below reduces a lot of code. However, it takes away the ability of VS Code to show docstrings below property names.
Is there a solution to this or a better method in general?
CodePudding user response:
Unless VS Code supports PEP-257's definition of attribute docstrings, this can only be considered an extended comment rather than a proper answer. I have never used VS Code and cannot test its support for this.
In its defense, it supplies the docstring syntactically, rather than setting the __doc__
attribute dynamically at runtime, so there's a chance it will resolve the main issue raised in the question.
If I weren't concerned with IDE support, I would write a custom descriptor and follow PEP-257 guidelines for attribute docstrings.
# 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"""