一、基础知识
- 基本术语:
类(class)----具有相同属性和方法的一些对象的集合,也可称之为类对象,对象是类的实例。
class A: #定义类,类名称为A
pass #此处用pass来“占位”,根据具体情况将pass替换为相应的功能代码
类变量----定义在类中的函数体(或叫做成员方法)之外。类变量在类的所有实例化对象中是共享的,所有实例对象都可以访问调用。类变量也是动态的,类变量一旦被修改了,所有实例对象读取到的值都会修改。
class Car(object):
price=1000000 #类变量,属于类的数据成员,所有的Car类实例化的对象都能给狗访问调用price这个变量,但在具体实例中无法修改,只能在类内部修改
def __init__(self,color): #self代表具体实例化对象instance,color是实例变量是属于对象的数据成员,不同的实例化对象中这个参数是互相不影响的。
self.color=color
数据成员----包括类变量(即属于类的数据成员)和实例变量(即属于对象的数据成员),是类和实例中的数据变量的总称。
实例变量----定义在类的成员方法或者说函数体中的变量,只作为当前实例的属性。不同实例之间这个变量是不会相互影响的。实例变量通常是在构造函数_ _ init _ _()中定义的,也可在其他成员方法中定义,定义和使用时必需以self为前缀。
class Car(object):
price=1000000
def __init__(self,color):
self.color=color
#此例中price即为类变量,color即为实例变量,color在init函数中定义且以self为前缀。
成员方法----类中定义的函数,用来描述对象所具有的行为和需要进行的操作。大致分为:公有方法、私有方法、静态方法和类方法。注意类中的函数第一个必须为_ _ init _ _()
,用于定义实例变量和传递参数等;而init函数和普通函数一样可以接受多个参数,但第一个参数必须是self
,此处的self代表的是一个对象object,指的是当前类的实例。
class Test():
def __init__(self,value): #构造函数为类中第一个函数,且第一个参数为self用于代表实例本身
self.__value=value
def value(self): #其他成员方法,指定具体实例对象传参后的动作
return self.__value
实例化----创建一个类的实例,即类的具体对象。
class Car(object):
price=1000000
def __init__(self,color):
self.color=color
#类定义
car1=Car('red')
#实例化,实例参数为车的颜色:‘red’
实例对象:通过类定义的数据结构实例。对象是类的一个具体实例,因此实例化后的类的全部数据成员和成员方法都“暂时”归属于此对象。所谓暂时是指在整个的实例化过程中,实例化对象执行完成后所有的实参都不会保留到类中也不会影响最初的类,以供下一次实例化。上述例中的car1就是实例化后的实例对象,被保存到变量car1中,可见类的实例化不是在类本身进行原地操作,因此不会影响到类被再次实例化。
类的成员----数据成员和成员方法统称为类的成员,其中数据成员包括属于类的数据成员(类变量)和属于对象的数据成员(实例变量)。而类的成员按照其保护机制又分为:公有成员和私有成员。公有成员在类的内部和外部均可直接访问;而私有成员(在定义时常以两个下划线_ _开头)在类的外部不能直接访问,但可以通过调用类的公有成员方法来访问,同时Python还提供了“对象名.类名 _xxx”来访问私有成员(通常不建议此种方式访问,会破坏类的封装性)。
类中以下划线开头和结尾的成员有特殊含义:
_xxx:保护成员,只有类和子类对象可以访问
_ _ xxx _ _:系统定义的特殊成员
_ _xxx:私有成员
class Q:
def __init__(self,value=0,value2=0):#构造函数
self._value1=value1
self.__value2=value2
def setValue(self,value1,value2):#成员方法
self._value1=value1
self.__value2=value2
def show(self):#成员方法
print(self._value1)
print(self.__value2)
>>>a=Q()
>>>a._value1
0 #类的外部可以直接访问非私有成员
>>>a._Q__value2
0 #类的外部通过特殊方法访问私有成员
继承----即派生类继承基类的字段和方法,继承也允许把一个派生类的对象作为一个基类对象对待,即允许再派生孙类(对于派生类,要将所有基类放到一对圆括号中逗号隔开)。如果需要在派生类中调用基类的方法可以使用内置函数super()或者通过“基类名.方法名()”来实现。继承是代码复用和设计复用的重要途径,也是实现多态的必要条件之一。
方法重写----从父类继承的方法子类可以对其进行改写(override),也称为方法的重写。其实相当于只是在派生类中添加了同名方法,以至于查询方法时不会再向基类查询。
#基类必须继承于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):
print('name must be string')
#如果数据不合法则采用默认值
self.__name=''
return
self.__name=name
def setAge(self,age):
if type(age)!=int:
print('age must be integer!')
self.__age=20
return
self.__age=age
def setSex(self,sex):
if sex not in('man','woman'):
print('sex must be ''man'' or ''woman''!')
self.__sex='man'
return
self.__sex=sex
def show(self):
print(self.__name,self.__age,self.__sex,sep='\n')
#派生类
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:
print('department must be a string')
self.__department='computer'
return
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('='*30)
#创建派生类的对象
lisi=Teacher('li si',32,'man','math')
lisi.show()
#调用继承的方法修改年龄
lisi.setAge(40)
lisi.show()
Python:类的继承,调用父类的属性和方法基础详解
属性----属性结合了公开数据成员和成员方法的优点,既可以像成员方法那样对值进行必要的检查,又可以像数据成员那样灵活的访问。
表:Python 类特殊方法
方法 | 功能说明 |
---|---|
_ _ new _ _() | 类的静态方法。用于确定是否要创建对象 |
_ _ init _ _() | 构造函数,生成对象(或者说创建了这个类的实例)时调用(设置初值及初始化) |
_ _del _ _() | 析构函数,释放对象时调用 |
_ _ add _ _() | + |
_ _ sub _ _() | - |
_ _mul _ _() | * |
_ _ truediv _ _() | / |
_ _floordiv _ _() | // |
_ _mod _ _() | % |
_ _pow _ _() | ** |
_ _repr _ _() | 打印、转换 |
_ _setitem _ _() | 按照索引赋值 |
_ _getitem _ _() | 按照索引获取值 |
_ _len _ _() | 计算长度 |
_ _call _ _() | 函数调用 |
_ _contains _ _() | in |
_ _eq _ _()、 _ _ ne _ _()、 _ _ lt _ _()、 _ _le _ _()、 _ _ gt _ _()、 _ _ ge _ _() | ==、!=、<、<=、>、>= |
_ _ str _ _() | 转化为字符串 |
_ _ lshift _ _()、 _ _ rshift _ _() | <<、>> |
_ _ and _ _ () 、_ _ or _ _()、 _ _ invert _ _() 、 _ _ xor _ _() | &、 |
_ _ iadd _ _() 、 _ _ isub _ _() | +=、-+ |
二、综合实例分析
自定义二叉树----设计二叉树类,模拟二叉树创建、插入子节点以及前序遍历、中序遍历和后序遍历等遍历方式,同时还支持二叉树中任意子树的节点遍历。
class BinaryTree:
def __init__(self,value):
self.__left=None
self.__right=None
self.__data=value
def __del__(self): #析构函数
del self.__data
def insertLeftChild(self,value): #创建左子树
if self.__left:
print('left child tree already exists')
else:
self.__left=BinaryTree(value)
return self.__left
def insertRightChild(self,value): #创建右子树
if self.__right:
print('right child trrr already exists')
else:
self.__right=BinaryTree(value)
return self.__right
def show(self):
print(self.__data)
def preOrder(self): #前序遍历
print(self.__data) #输出根节点的值
if self.__left:
self.__left.preOrder() #遍历左子树
if self.__right:
self.__right.preOrder() #遍历右子树
def postOrder(self): #后序遍历
if self.__left:
self.__left.postOrder()
if self.__right:
self.__right.postorDer()
print(self.__data)
def inOrder(self): #中序遍历
if self.__left:
self.__left.inOrder()
print(self.__data)
if self.__right:
self.__right.inOrder()
if __name__ == '__main__':
print('please use me as a momdule')
转载:
Python面向对象编程指南
关于面向对象内容多知识点晦涩,应用也灵活,此篇博文会继续完善更新。感谢清华大学董付国老师及其编著的《Python可以这样学》