与C++和JAVA一样,python也是一种面向对象的语言,但具体使用和C++有一些不同之处。下面按照封装、继承、多态的顺序对python面向对象编程进行一个总结。
封装
class testclass1:
def __init__(self):
print(__name__)
def class1fun(self,a,b):
print(a+b)
__pri = 0 #private变量,只能类内部调用
_pro = 0 #protected变量,只能类内部调用
def __prifun(self):
print('this is a private function')
def _profun(self):
print('this is a protected function')
用C++类比,则__init__函数相当于构造函数。命名最前面有两个_的函数或者变量为private形,一个_就是protected形,没有当然就是public。但是python实际的做法是把变量的名字用 _classname__变量名 来替换了这个变量,在类外仍然可以用这个名字来访问。.self基本可以类比于this指针,self代表形参中有一个是类的实例。在每个类内函数的形参中第一个必须为self.所有函数都可以重载。
同时类内都具有一系列的专用方法(来自菜鸟教程),也都可以重载:
__init__ : 构造函数,在生成对象时调用
__del__ : 析构函数,释放对象时使用
__repr__ : 打印,转换
__setitem__ : 按照索引赋值
__getitem__: 按照索引获取值
__len__: 获得长度
__cmp__: 比较运算
__call__: 函数调用
以下为运算符,可以重载,相当于operator x 的重载:
__add__: 加运算__sub__: 减运算
__mul__: 乘运算
__div__: 除运算
__mod__: 求余运算
__pow__: 乘方
可以使用点(.)来访问对象的属性,经过测试,需要是在__init__()函数内部定义的self.x形式的属性
也可以使用以下函数的方式来访问属性:
getattr(obj, name,[default]) : 访问对象的属性
hasattr(obj,name) : 检查是否存在一个属性
- setattr(obj,name,value) : 设置一个属性。如果属性不存在,会创建一个新属性
- delattr(obj, name) : 删除属性
Python内置类属性
__dict__ : 类的属性(包含一个字典,由类的数据属性组成)
__doc__ :类的文档字符串
__name__: 类名
__module__: 类定义所在的模块(类的全名是'__main__.className',如果类位于一个导入模块mymod中,那么className.__module__ 等于 mymod)
__bases__ : 类的所有父类构成元素(包含了以个由所有父类组成的元组)
继承
写出一个testclass1类的子类:
class childclass1(testclass1):
def newfunc(self):
self._profun()
# self.__prifun() #子类对象使用会报错
在新定义的函数中的_profun和__prifun函数分别为testclass1类中的protected和private函数。保护变量和函数在子类中被继承,但不可以外部引用,private型则不可被子类对象访问。但需要注意,不可被子类对象访问,但在子类调用可访问的父类函数时,函数内部会根据需要调用父类的private变量和函数。
实际上,在写自己的父类的时候,我们已经用到了继承所有类都继承自Object类。上面的类实际可以写成:
class testclass1(Object): #后省略
python支持多继承。
class childclass1(testclass1,testclass2,...):
子类可以使用多个父类中的变量和函数。
多态
多态是类和继承中最容易出错的地方。
首先,python没有重载和虚函数,没有重载和虚函数,没有重载和虚函数!!!python子类和父类同名函数只能是重写关系,即参数个数和函数名都一样,不能使用重定义。
当子类对象要调用父类被重写的函数时,使用super()函数定义一个超类:
super(type,[object-or-type])
super类的定义比较复杂,我们可以直接注意使用方法,大体有两种:
super(类名,self).fun or var #用于在子类内部使用父类的方法
super(类名,类的对象).fun or var #用于在声明子类对象后使用父类方法
多继承时,如果几个父类有相同的函数,在super调用的时候会调用排名最靠前的父类函数。