Keeping attribute names simple when using getters and setters
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'