Keeping attribute names simple when using getters and setters Is the use of _pn in __init__ pythonic? It seems that most examples change the actual attribute to self._pn to indicate it's private, but I would like to be able to call self.pn but have the advantage of checks with setters.

The following code will cause a recursive loop:

class part:
'Holds various attributes of interest for a part number'
def __init__(self, pn):
    self.pn = pn

def set_pn(self, pn):
    if type(pn) != str:
        raise Exception("Part number needs to be a string")
    self.pn = _pn

pn = property(fset = set_pn)


The following won't, but I'm not sure if _pn is pythonic:

class part:
'Holds various attributes of interest for a part number'
def __init__(self, _pn):
    self.pn = _pn

def set_pn(self, pn):
    if type(pn) != str:
        raise Exception("Part number needs to be a string")
    self.pn = _pn

_pn = property(fset = set_pn)
I think this is the best way to do it:

class Part(object):
    def __init__(self, pn):
        self.pn = pn

    @property
    def pn(self):
        return self._pn

    @pn.setter
    def pn(self, value):
        if type(value) != str:
            raise Exception("Part number must be a string")
        self._pn = value


Remarks:


The _ prefix for properties is well-accepted, see the docs
self.pn = pn is to reuse the validation implemented in the setter
Class names should be CamelCase
Modern classes should extend object (class Part(object): ... as opposed to plain class Path: ...)
Doc strings should be """class description""" instead of 'class description'