Question: I'm new to Python and I find that when making classes I keep having to write @property def example(self): return self._example @example.setter def example(self, example): if #some conditions here: self._example = example  I am working on a project and there are over a dozen of these across it, so I tried to make a function that would take a property name and some conditions and make a getter, setter and deleter for it. class Util: @classmethod def custom_property(cls, prop, conds=None, deletable=False): def getter(self): return getattr(self, f'_{prop}') def setter(self, value): if conds is None or conds(value): setattr(self, f'_{prop}', value) else: raise ValueError(f'Invalid value for {prop}') def deleter(self): if deletable: del self._value else: print("This attribute can't be deleted.") # setattr(target, prop, property(getter, setter, deleter)) return [getter, setter, deleter]  and here is an example of me trying to use it: from utils import Util def name_conds(name): if not isinstance(name, str): raise TypeError("City name must be a string") if not name.strip(): raise ValueError("City name cannot be blank") if not 2 <= len(name) <= 25: raise ValueError("City name length must be between 2 and 25 characters") return True class City: def __init__(self, name): self._name = name [name_getter, name_setter, name_deleter] = Util.custom_property("name", name_conds) name = property(name_getter, name_setter, name_deleter)  Unfortunately, this doesn't totally work. If I make a city with a name "asdf" and try to change it to "a", I get the right error that the length is wrong, but if I instantiate a new city with a name "a", I am allowed to with no problem. Surely there is some way people have gotten around writing properties out like I have? Also, as the commented line in Util shows, I wanted to be able to use the method in a quicker way by just calling Util.custom_property inside whatever class needed a property, but that added the property to Util (of course, since it is adding it to cls). It seems there is no way to give the class City as an argument inside City, but then calling custom_property outside of city might mean the functions in city can't reference name properly.

Answer: The problem isn't with your property, but with the fact that you aren't using the property in City.__init__. _name is really a private implementation detail of the property itself (though the value is stored on the instance of City), so City methods should not use it directly, either.  While I'm answering the question, I'll point out that custom_property doesn't have to be a class method (or a method of any class); it can be an ordinary function. Further, it can return a property instance itself that you can assign directly to an attribute of City. Finally, you can optimize setter by defining one that unconditionally sets the value if conds is None, and you can just omit the deleter if deletable is False. def custom_property(cls, prop, conds=None, deletable=False): name = f'_{prop}' def getter(self): return getattr(self, name) if conds is None: def setter(self, value): setattr(self, name, value) else: def setter(self, value): if conds(value): setattr(self, name, value) else: raise ValueError(f'Invalid value for {prop}') if deletable: def deleter(self): delattr(self, name) else: deleter = None return property(getter, setter, deleter)  Then from utils import custom_property def name_conds(name): if not isinstance(name, str): raise TypeError("City name must be a string") if not name.strip(): raise ValueError("City name cannot be blank") if not 2 <= len(name) <= 25: raise ValueError("City name length must be between 2 and 25 characters") return True class City: def __init__(self, name): self.name = name # Use the property, not _name name = custom_property("name", name_conds)