python的类(面向对象程序设计OOP)

#类的定义与实例化
#Python使用class关键字来定义类
class Car(object): #定义一个类,派生自object类
def infor(self): #定义成员方法
print("This is a car")
car = Car() #实例化对象
car.infor() #调用对象的成员方法
#可以使用内置函数isinstance()来测试一个对象是否为某个类的实例
print(isinstance(car,Car))

#数据成员和成员方法统称为类的成员,成员又分为私有成员和公有成员
#私有成员:在类的外部不能直接访问,一般是在类的内部进行访问和操作,或者在类的外部通过调用对象的公有成员方法来访问,这是类的封装特性的重要体现。
#在定义类的成员时,如果成员名以两个下划线"__"开头则表示是私有成员,通过"对象名._类名__xxx"也可以在外部访问私有成员,
class A:
def __init__(self, value1=0, value2=0): #构造方法
self._value1 = value1
self.__value2 = value2 #私有成员

def setValue(self, value1, value2): #成员方法,公有成员
self._value1 = value1
self.__value2 = value2 #在类内部可以直接访问私有成员
a = A()
print(a._value1)
print(a._A__value2)

#以下画线开头和结束的成员名有特殊的含义,在类的定义中用下画线作为变量名和方法名前缀和后缀往往表示类的特殊成员。
#_xxx:以一个下画线开头,表示保护成员,不能用"from module import *"导入,只有类对象和子类对象可以访问这些成员。
#__xxx:以两个下画线开头,表示类中私有成员,一般只有类对象自己能访问,子类对象也不能直接访问该成员
#__xxx__:前后各两个下画线,表示系统定义的特殊成员。

#数据成员
#数据成员可以大致分为两类:属于对象的数据成员和属于类的数据成员
#①属于对象的数据成员一般在构造方法__init__()中定义,也可以在其他成员方法中定义,在定义和在实例方法中访问数据成员时往往以self作为前缀,
#同一个类的不同对象(实例)之间的数据成员之间互不影响。
#②属于类的数据成员是该类所有对象共享的,不属于任何一个对象,在定义类时这类数据成员一般不在任何一个成员方法的定义中。
class Car(object):
price = 100000 #属于类的数据成员
def __init__(self, c):
self.color = c #属于对象的数据成员
car1 = Car("red")
car1.price = 19
print(car1.price)
print(car1.color)

#成员方法
#成员方法常有的类型有:公有方法,私有方法,静态方法,类方法和抽象方法(公有方法、私有方法和抽象方法一般是指属于对象的实例方法)
#私有方法:只需要在函数名前加上 "__"两个下划线,声明该方法为私有方法,只能在类内进行调用,不能在类的外部调用
class animal(object):
def printname(self,name):
print(name)
def __printname(self,name): #私有方法,外界无法访问私有方法,但可以在类内部方法私有方法。
print(name)
cat = animal()
cat.printname("TOM")
#cat.__printname("TOM")

#公有方法:一般方法
class animal(object):
def printname(self,name):
print(name)
mouse = animal()
mouse.printname("Jim")

#静态方法:使用装饰器@staticmethod,静态方法是类中的函数,不需要实例。静态方法主要是用来存放逻辑性的代码,逻辑上属于类,
# 但是和类本身没有关系,也就是说在静态方法中,不会涉及到类中的属性和方法的操作。可以理解为,静态方法是个独立的、单纯的函数,
# 它仅仅托管于某个类的名称空间中,便于使用和维护。

#类方法:使用装饰器@classmethod,原则上,类方法是将类本身作为对象进行操作的方法。假设有个方法,且这个方法在逻辑上采用类本身作为对象来调用更合理,
# 那么这个方法就可以定义为类方法。另外,如果需要继承,也可以定义为类方法。

#魔法方法(特殊方法):
#①__init__:初始化函数,在创建实例对象为其赋值时使用。
#②__new__:很多人认为__init__是类的构造函数,其实不太确切,__init__更多的是负责初始化操作,相当于一个项目中的配置文件,__new__才是真正的构造函数,
# 创建并返回一个实例对象,如果__new__只调用了一次,就会得到一个对象。
#创建对象的步骤
#a、首先调用__new__得到一个对象
#b、调用__init__为对象添加属性
#c、将对象赋值给变量
#③__class__:获得已知对象的类 ( 对象.__class__)
#④__str__:在将对象转换成字符串 str(对象) 测试的时候,打印对象的信息
#⑤__repr__:如果说__str__体现的是一种可读性,是给用户看的,那么__repr__方法体现的则是一种准确性,是给开发人员看的,
# 它对应的是repr()函数,重构__repr__方法后,在控制台直接敲出实例对象的名称
#⑥__del__:对象在程序运行结束之后进行垃圾回收的时候调用这个方法,来释放资源。
#⑦__getattribute__:属性访问拦截器,在访问实例属性时自动调用。在python中,类的属性和方法都理解为属性,且均可以通过__getattribute__获取。
#⑧__bases__:获取指定类的所有父类构成元素,使用方法为类名.__bases__
#⑨__mro__:显示指定类的所有继承脉络和继承顺序,假如这个指定的类不具有某些方法和属性,但与其有血统关系的类中具有这些属性和方法,则在访问这个类本身不具有的这些方法和属性时,
# 会按照__mro__显示出来的顺序一层一层向后查找,直到找到为止。
#⑩__call__:具有__call__魔法方法的对象可以使用XXX()的形式被调用,比如说类的实例对象
class Entity:
'''调用实体来改变实体的位置。'''
def __init__(self, size, x, y):
self.x, self.y = x, y
self.size = size

def __call__(self, x, y):
'''改变实体的位置'''
self.x, self.y = x, y
e = Entity(1, 2, 3) # 创建实例
print(e.x)
print(e.y)
e(4, 5) #实例可以象函数那样执行,并传入x y值,修改对象的x y
print(e.x)
print(e.y)
#__slots__:可以限制实例对象的属性和方法,但是对类不起作用。

#继承的好处:设计一个新类时,如果可以继承一个已有的、设计良好的类然后进行二次开发,可以大幅度减少开发工作量,并且可以很大程度保证质量。
#在继承关系中,已有的、设计好的类称为父类,新设计的类称为子类。子类可以继承父类的公有成员,但是不能继承其私有成员。
#如果需要在子类中调用父类的方法,可以使用内置函数super()或者通过“父类名.方法名()”的方式来实现这一目的。
#例:设计Person类,并根据Person派生Teachet类,分别创建Person类与Teachet类的对象。

#父类
#父类必须继承于object,否则在子类中将无法使用super()函数
class Person(object):
def __init__(self, name='', age=20, sex='man'):
#通过调用方法进行初始化,这样对参数进行更好的控制
self.setName(name)
self.setAge(age)
self.setSex(sex)

def setName(self, name):
if not isinstance(name, str):
raise Exception('name must be string.')
self.__name = name

def setAge(self, age):
if type(age) != int:
raise Exception('age must be integer.')
self.__age = age

def setSex(self, sex):
if sex not in ('man', 'woman'):
raise Exception('sex must be "man" or "woman"')
self.__sex = sex

def show(self):
print(self.__name ,self.__age, self.__sex, end='')

#子类
class Teacher(Person):
def __init__(self, name='', age=30, sex='man', department='Computer'):
#调用基类构造方法,初始化基类的私有数据成员
super(Teacher, self).__init__(name, age, sex)
#也可以这样初始化基类的私有数据成员
#Person.__init__(self, name, age, sex)
#初始化派生类的数据成员
self.setDepartment(department)

def setDepartment(self, department):
if type(department) != str:
raise Exception('department must be a string')
self.__department = department

def show(self):
super(Teacher, self).show()
print(self.__department)

if __name__ == '__main__':
#创建基类对象
zhangsan = Person('Zhang San', 19, 'man')
zhangsan.show()
print('\n', '=' * 30)

#创建派生类对象
lisi = Teacher('Li si', 32, 'man', 'Match')
lisi.show()
#调用继承的方法修改年龄
lisi.setAge(40)
lisi.show()

猜你喜欢

转载自www.cnblogs.com/xhw19950606/p/12273100.html