Class
Vehicle
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
import typing
class Vehicle(object):
"""Document String: Define a Vehicle class"""
def __init__(self, brand: str, year: int):
self._brand = brand;
self._year = year;
@property
def brand(self) -> str:
return self._brand
@brand.setter
def brand(self, b : str) -> None:
self._brand = b;
@brand.deleter
def brand(self) -> None:
del self._brand
@property
def year(self) -> int:
return self._year
@year.setter
def year(self, y : int) -> None:
self._year = y
@year.deleter
def year(self) -> None:
del self._year
def __str__(self) -> str:
return self._brand+' '+str(self._year)
def __getattr__(self, attr) -> str: # intercept that inexistent attribute
return '~'
def main():
v = Vehicle("Lincoln", 1998);
print(v) # equals to print(v.__str__())
v.brand = "Honda"
v.year = 2016
print(v)
del v.year
print(v)
if __name__ == "__main__":
main()
Access Attributes
#!/usr/bin/python
from Vehicle import Vehicle
def main():
print('test ...')
v = Vehicle('Buick', 1998)
print(v.brand, v.year) # use accessors to access attributes
print(v._brand, v._year) # directly access class attributes
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()
Add attributes
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()
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