Class
Vehicle, Java style
class Vehicle(object):
    """Document String: Define a Vehicle class"""

    def __init__(self, brand, year):
	self.brand = brand;
	self.year = year;

    def getBrand(self):
        return self.brand

    def getYear(self):
        return self.year

    def setBrand(self, brand):
        self.brand = brand

    def setYear(self, year):
        self.year = year

    def __str__(self):
        return str(self.brand)+" "+str(self.year)

def main():
    v = Vehicle("Lincoln", 1998);
    print("Brand: %s, Year: %d" % (v.getBrand(), v.getYear()))
    print(v)

    v.setBrand("Honda")
    v.setYear(2016)

    print("Brand: %s, Year: %d" % (v.getBrand(), v.getYear()))
    print(v)

if __name__ == "__main__":
	main()
		
Access
  • In Python, an object's attributes may always be accessed, there is no way to prevent other code from accessing the data
  • #!/usr/bin/python
    
    from Vehicle import Vehicle
    
    def main():
        v = Vehicle("Lincolin", 1998)
    
        print v.brand, v.year
    
        v.brand = "Honda"
        v.year = 2016
    
        print v
    
    if __name__ == '__main__':
        main()
    		
    Controlling Access to Attributes
  • when a class author creates an attribute with a single leading underscore, the author does not want users of the class to access the attribute directly
  • the attribute with single leading underscore is still able to be accessed directly
  • class Vehicle(object):
        """Document String: Define a Vehicle class"""
    
        def __init__(self, brand, year):
            self._brand = brand;
    	self._year = year;
    
        def getBrand(self):
            return self._brand
    
        def getYear(self):
            return self._year
    
        def setBrand(self, brand):
            self._brand = brand
    
        def setYear(self, year):
            self._year = year
    
        def delBrand(self):
            del self._brand
    
        def delYear(self):
            del self._year
    
        def __str__(self):
            return self._brand+' '+str(self._year)
    
        def __getattr__(self, attr): # intercept that inexistent attribute
            return '~'
    
        # If c is an instance of C, c.x will invoke the getter, c.x = value will invoke the setter and del c.x the deleter
        # set up getter, setter, and deleter
        year = property(getYear, setYear, delYear, 'doc of year ...') # access self._year by year
        brand = property(getBrand, setBrand, delBrand, 'doc of brand ...') # access self._brand by brand
    
    def main():
        v = Vehicle("Lincoln", 1998);
    
        print("Brand: %s, Year: %d" % (v.brand, v.year))
    
        v.brand = "Honda"
        v.year = 2016
        print(v)
        print(v._brand) # access self._brand directly
    
        del v.year
        print(v)
    
    if __name__ == "__main__":
    	main()
    		
    class Vehicle(object):
        """Document String: Define a Vehicle class"""
    
        def __init__(self, brand, year):
            self._brand = brand;
    	self._year = year;
    
        @property
        def brand(self):
            return self._brand
    
        @brand.setter
        def brand(self, b):
            self._brand = b;
    
        @brand.deleter
        def brand(self):
            del self._brand
    
        @property
        def year(self):
            return self._year
    
        @year.setter
        def year(self, y):
            self._year = y
    
        @year.deleter
        def year(self):
            del self._year
    
        def __str__(self):
            return self._brand+' '+str(self._year)
    
        def __getattr__(self, attr): # intercept that inexistent attribute
            return '~'
    
    def main():
        v = Vehicle("Lincoln", 1998);
    
        print("Brand: %s, Year: %d" % (v.brand, v.year))
    
        v.brand = "Honda"
        v.year = 2016
        print(v)
        print(v._brand) # access self._brand directly
    
        del v.year
        print(v)
    
    if __name__ == "__main__":
    	main()
    		
    Add attributes in a function
    class Vehicle(object):
        """Document String: Define a Vehicle class"""
    
        def __init__(self, brand):
            self._brand = brand;
    
        @property
        def brand(self):
            return self._brand
    
        @brand.setter
        def brand(self, b):
            self._brand = b;
    
        @brand.deleter
        def brand(self):
            del self._brand
    
        @property
        def year(self):
            return self._year
    
        @year.setter
        def year(self, y):
            self._year = y
    
        @year.deleter
        def year(self):
            del self._year
    
        def __str__(self):
            return self._brand+' '+str(self._year)
    
        def __getattr__(self, attr): # intercept that inexistent attribute
            return '~'
    
    def main():
        v = Vehicle("Lincoln");
    
        v.year = 1998
    
        print(v)
    
    if __name__ == "__main__":
    	main()
    		
    Control attributes with built-in functions
    class Vehicle(object):
        """Document String: Define a Vehicle class"""
    
        def __init__(self, brand, year):
    	#print "Create Vehicle Object ...";
    	self._brand = brand;
    	self._year = year;
    
        @property
        def brand(self):
            return self._brand
    
        @brand.setter
        def brand(self, b):
            self._brand = b;
    
        @brand.deleter
        def brand(self):
            del self._brand
    
        @property
        def year(self):
            return self._year
    
        @year.setter
        def year(self, y):
            self._year = y
    
        @year.deleter
        def year(self):
            del self._year
    
        def __str__(self):
            return str(self.brand)+" "+str(self.year)
    
        def __getattr__(self, attr): # intercept that inexistent attribute
            return '~'
    
    def main():
    	v = Vehicle("Lincoln", 1998);
            print(v)
    
    	setattr(v, 'year', 2000); # use setattr() and setter
    	setattr(v, 'brand', 'Buick');
            print(v)
    
    	if hasattr(v, 'year'):
    		print "Year Attribute: ", getattr(v, 'year'); # use getattr() and getter
    
    	delattr(v, 'year');
    	print "Year Attribute: ",getattr(v, 'year');
    
    if __name__ == "__main__":
    	main()
    		
    Private attributes
  • Prevent access attributes directly, prefix the name of the attribute with two underscore
  • Name mangling with create an attribute, _ClassName__attribute
  • class Vehicle(object):
        """Document String: Define a Vehicle class"""
    
        def __init__(self, brand):
            self.__brand = brand;
    
        @property
        def brand(self):
            return self.__brand
    
        @brand.setter
        def brand(self, b):
            self.__brand = b;
    
        @brand.deleter
        def brand(self):
            del self.__brand
    
        def __str__(self):
            return self.__brand
    
        def __getattr__(self, attr): # intercept that inexistent attribute
            return '~'
    
    def main():
        v = Vehicle("Lincoln");
    
        print("Brand: %s" % (v.brand)) # use getter to access attribute
        print("Brand: %s" % getattr(v, 'brand')) # use getattr() and getter
    
        print("Brand: %s" % v.__brand) # not able to access self.__brand
        print("Brand: %s" % v._Vehicle__brand) # name mangling
    
    if __name__ == "__main__":
    	main()
    		
    Using default arguments with constructors
    class Vehicle(object):
        """Document String: Define a Vehicle class"""
    
        def __init__(self, brand = "None", year = 0):
            self._brand = brand;
    	self._year = year;
    
        @property
        def brand(self):
            return self._brand
    
        @brand.setter
        def brand(self, b):
            self._brand = b;
    
        @brand.deleter
        def brand(self):
            del self._brand
    
        @property
        def year(self):
            return self._year
    
        @year.setter
        def year(self, y):
            self._year = y
    
        @year.deleter
        def year(self):
            del self._year
    
        def __str__(self):
            return self._brand+' '+str(self._year)
    
        def __getattr__(self, attr): # intercept that inexistent attribute
            return '~'
    
    def main():
        v = Vehicle("Lincoln", 1998); # Lincoln 1998
        print(v)
    
        v = Vehicle("Lincoln"); # Lincoln 0
        print(v)
    
        v = Vehicle(year = 1998) # None 1998
        print(v)
    
    if __name__ == "__main__":
    	main()
    		
    Class attributes and deconstructor
    class Vehicle(object):
        """ Vehicle class """
    
        count = 0; # class attribute
    
        def __init__(self, brand):
            self.__brand = brand
            Vehicle.count += 1
    
        @property
        def brand(self):
            return self.__brand
    
        @brand.setter
        def brand(self, b):
            self.__brand = b
    
        @brand.deleter
        def brand(self):
            del self.__brand
    
        def __str__(self):
            return "Brand: %s" % self.__brand
    
        def __getattr__(self, attr):
            return "~"
    
        def __del__(self):
            Vehicle.count -= 1
            print("Delete %s, %d vehicles left ..." % (self.__brand, Vehicle.count))
    
    def main():
        v1 = Vehicle("Lincoln")
        v2 = Vehicle("Buick")
        v3 = Vehicle("Acura")
        v4 = Vehicle("Honda")
    
        del v1
        del v2
    
    if __name__ == '__main__':
        main()
    		
    Call its own method
    class T(object):
        def __init__(self, n):
            self.n = n
    
        def show(self):
            return self.n
    
        def callShow(self):
            return self.show()
            #return T.show(self)
    
    def main():
        t = T(10)
    
        print(t.show())
        print(t.callShow())
    
    if __name__ == '__main__':
        main()
    		
    __slots__
  • list the only attributes that objects of the class are allowed to have
  • class Vehicle(object):
        """Document String: Define a Vehicle class"""
     
        __slots__ = ['_brand', '_year', '_model']
    
        def __init__(self, brand, year):
            self._brand = brand;
    	self._year = year;
     
        def __str__(self):
            return self._brand+' '+str(self._year)+' '+self._model
    
        def __getattr__(self, name):
            return 'None'
    
    def main():
        v = Vehicle("Buick", 1998) # by default, only _brand and _year
        print(v)
    
        v._model = 'Century' # add attribute, _model
        print(v)
    
        v._color = 'White' # not allow to add _color which is not in __slots__
    
    if __name__ == '__main__':
        main()
    		
    Reference
  • Python How to Program, Chapter 7