面向对象编程(OOP:Object Oriented Programming)是一种程序设计思想,它把对象作为程序的基本单元,一个对象包含了数据和操作数据的函数。
面向对象的程序设计把计算机程序视为一组对象集合,每个对象都可以接收其他对象发过来的消息,并处理这些消息,计算机的执行就是一系列消息在各个对象之间传递。
在Python中,所有数据类型都可以视为对象,也可以自定义对象。自定义的对象数据类型就是面向对象中的类(Class)的概念。
面向对象的设计思想:抽象出Class(类),根据Class创建Instance(实例)。面向对象的特点:数据封装、继承和多态。
1、创建类
在Python中,通过关键字Class定义类:
class ClassName:
‘类的帮组信息’ #类文档字符串
Class_suite #类体,由类成员,方法,数据属性组成
比如:
class Student(object):
... stdCount = 0
... def __init__(self, name, score):
... self.__name = name
... self.score = score
... def print_score(self):
... print("%s: %s" % (self.__name, self.score))
... def get_grade(self):
... if self.score >= 90:
... return 'A'
... elif self.score >=60:
... return 'B'
... else:
... return 'C'
注:特殊方法“init”前后分别有两个下划线!!!!
1)stdCount变量是一个类变量,它的值在Student类的所有实例之间共享,在内部类或外部类中可以使用Student.stdCount访问;
2)方法__init__是一个特殊的方法,称为类的构造函数或初始化方法,在创建类实例时会调用该方法;
3)方法__del__是类的析构函数,在对象销毁时被调用;
4)Self代表类的实例(不是类),在定义类的方法时必须有,但外部程序在调用类的方法时不需要传入相应的参数,Python解释器会自动将实例变量传进去。
注:有了__init__方法后,在创建类的实例时,就不能传入控的参数了,必须传入与__init__方法匹配的参数:
>>> bart = Student("ssy", 80)
2、创建实例对象
创建实例对象的方法:类名 + (),比如:
>>> class Animal(object):
... def run(self):
... print ("Animal is running")
...
>>> animal = Animal()
>>> animal
<__main__.Animal object at 0x036F44D0>
>>> Animal
<class '__main__.Animal'>
变量animal指向的是一个Animal类的实例,0x036F44D0是内存地址。
3、类的属性和方法
1)属性访问
访问属性的方法:类名 + . + 变量名(或方法名)
比如:
>>> bart = Student("ssy", 80)
>>> bart.score
80
>>> bart.print_score()
ssy: 80
>>>
2)数据封装
数据封装是面向对象编程的一个重要特点。在Student类中,每个实例都拥有各自的属性:__name和score。既可以直接访问,也可以通过外部函数来访问这些数据,比如:
>>> bart.score
80
>>> def print_std_score(std):
... print("%s" % (std.score))
...
>>> print_std_score(bart)
80
>>>
因此,可以在Student类中定义访问数据的函数(将“数据”封装起来),这些封装数据的函数称之为类的方法。比如Student类中定义的print_score方法:
>>> bart.print_score()
ssy: 80
>>>
类的方法就是与实例绑定的函数,和普通函数不同,方法可以直接访问实例的数据。通过在实例上调用方法,可以直接操作对象内部的数据,而无需关系方法内部的实现细节。
在Python类的内部,使用 def 关键字可以为类定义一个方法,与一般函数定义不同,类方法必须包含参数 self,且为第一个参数。
3)访问限制
从Student类的定义来看,虽然类的方法(类的数据封装特性)对外屏蔽了内部实现的复杂性,但是,外部代码还是可以直接访问实例对象的属性score:
>>> bart.score
80
在Python中,类的属性名如果以__开头(比如:__Private_Attr),则表示这个属性是类的私有变量(Private),外部不能直接访问:
>>> bart.__name
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Student' object has no attribute '__name'
>>>
同理,在Python中,若类的方法名以__开头(比如:__Private_Method),则该方法为私有方法,不能在类的外部调用。在类的内部调用方式如下: self.__private_methods。
单下划线、双下划线和头尾双下划线说明:
1、foo:定义的是特殊方法,一般是系统定义名字 ,类似 init() 之类的。
2、_foo:单下划线开头的变量是protected 类型的变量(即保护类型),只允许类本身与子类访问,不能用于 from module import *。
3、__foo:双下划线开头的变量的是私有类型变量,只允许类本身访问。
注:以双下划线开头的变量,Python解释器将此变量改成了“_类名__变量名”,所以,外部无法直接通过“__变量名”访问,但是如果通过“_类名__变量名”的方式也是可以直接访问的。
4)Python内置类属性
Python内置类属性包括:
__dict__:类的属性,包含一个字典,由类的数据属性组成;
__doc__:类的文档字符串;
__name__:类名;
__module__:类定义所在的模块,类的全名是“main.className”,如果类位于模块mymod中,则className.module__等于mymod;
__bases:类的所有父类构成元素,包含一个由所有父类组成的元组;
比如:
#!/usr/bin/python
class Employee:
'所有员工的基类'
empCount = 0
def __init__(self, name, salary):
self.name = name
self.salary = salary
Employee.empCount += 1
def displayCount(self):
print "Total Employee %d" % Employee.empCount
def displayEmployee(self):
print "Name : ", self.name, ", Salary: ", self.salary
print "Employee.__doc__:", Employee.__doc__
print "Employee.__name__:", Employee.__name__
print "Employee.__module__:", Employee.__module__
print "Employee.__bases__:", Employee.__bases__
print "Employee.__dict__:", Employee.__dict__
5、类的继承
在定义一个Class时,可以从现有的Class继承,新的Class称为子类,而被继承的Class称为基类、父类或超类。通过继承机制,可以实现代码的重用。
类的继承语法:
class 派生类名(基类名):
... ...
在Python中,类的继承的一些特点如下:
如果在子类中需要父类的构造方法,就需要显示调用父类的构造方法,或者不重写父类的构造方法。
在调用基类的方法时,需要加上基类的类名前缀,且需要带上self参数变量。区别在于类中调用普通函数时并不需要带上self参数。
Python找到类型的方法属性:首先在派生类中找到对应的方法,如果找不到,才会在基类中查找。
如果在继承元组中列了一个以上的类,那么称为“多重继承”,语法如下:
class SubClassName (ParentClass1[, ParentClass2, ...]):
...
可以使用issubclass()或isinstance()方法检测:
issubclass():判断一个类是否是雷一个类的子类,语法:issubclass(sub, sup)
isinstance(obj, Class):如果obj是Class类的实例对象或是Class子类的实例对象,则返回True。
1)方法重写
如果父类方法的功能不能满足需求,则可以在子类中重写父类的方法。
2)基础重载方法
1 init(self[, args …]):构造方法
调用方法:obj = className(args)
2 del(self):析构方法,删除一个对象
调用方法:del obj
3 repr(self):转化为供解释器读取的形式
调用方法:repr(obj)
4 str(self):将值转化为适合人阅读的形式
调用方法:str(obj)
5 cmp(self, x):对象比较
调用方法:cmp(obj, x)
3)运算符重载
Python也支持运算符重载,如下:
#!/usr/bin/python
class Vector:
def __init__(self, a, b):
self.a = a
self.b = b
def __str__(self):
return 'Vector (%d, %d)' % (self.a, self.b)
def __add__(self,other):
return Vector(self.a + other.a, self.b + other.b)
v1 = Vector(2,10)
v2 = Vector(5,-2)
print v1 + v2
参考文档:
http://www.runoob.com/python/python-object.html
https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/001431865288798deef438d865e4c2985acff7e9fad15e3000