一.面向对象的概述
1.对象
对象,是一个抽象概念,英文称作“Object”,表示任意存在的事物。在Python中,一切都是对象。即不仅是具体的事物称之为对象,字符串、函数等也都是对象。这说明python天生就是面向对象的。
一个对象即是一个类的实例化后实例,一个类必须经过实例化后方可在程序中调用,一个类可以实例化多个对象,每个对象亦可以有不同属性,就像人类是指所有人,每个人是指具体的对象,人与人之间有共性,亦有不同。
2.类
类是封装对象的属性和行为的载体,反过来说具有相同属性和行为的一类实体被称为类。在python语言中,类是一个抽象的概念,对象是类的实例。例如把猫群比作猫类,那么猫类就具备了耳朵、尾巴、胡须、爪等属性,觅食、跑、睡觉等行为,而一只在客厅里跑来跑去的猫则被视为猫类的一个对象。
一个类即是对一类拥有相同属性的对象的抽象、蓝图、原型。在类中定义了这些对象的都具备的属性、共同方法。
二.面向对象程序设计的特点
面向对象程序设计具有三大基本特征:封装、继承和多态。
1.封装
封装是面向对象编程的核心思想,将对象的属性和行为封装起来,其载体就是类,类通常会对客户隐藏其实现细节,这就是封装的思想。例如,用户使用计算机,只需要使用手指敲击键盘就可以实现一些功能,而不需要知道计算机内部是如何工作的。
采用封装思想保证了类内部数据结构的完整性,使用该类的用户不能直接看到类中的数据结构,而只能执行类允许公开的数据,这样就避免了外部对内部数据的影响,提高了程序的可维护性。
2.继承
一个类可以派生出子类,在这个父类里定义的属性、方法自动被子类继承。在python中可以说子类的实例都是父类的实例,但不能说父类的实例是子类的实例。继承是实现重复利用的重要手段,子类通过继承复用了父类的属性和行为的同时又添加了子类特有的属性和行为。
3.多态
将父类对象应用于子类的特征就是多态。
4.区分面向对象和面向过程
面向对象 华山派 独门秘籍:类 class
面向过程 逍遥派 独门秘籍:过程 def
三.类的定义和使用
1.定义类
在python中,类的定义使用class关键字来实现,语法如下:
class ClassName:
'''类的帮助信息''' #类文档字符串
statement #类体
参数说明:
ClassName:用于指定类名,一般使用大写字母开头,如果类名中包括两个单词,第二个单词的首字母也大写,这种命名方法也称为“驼峰式命名法”,这是惯例。
“类的帮助信息”:用于指定类的文档字符串,定义该字符串后,在创建类的对象时,输入类名和左侧的括号“(”后,将显示该信息。
statement:类体,主要由类变量(或类成员)、方法和属性等定义语句组成。如果在定义时,没想好类的具体功能,也可以在类体中直接使用pass语句代替。
2.创建类的实例
语法格式:ClassName(parameterlist)
注:其中,ClassName是必选参数,用于指定具体的类;parameterlist是可选参数,当创建一个类时,没有创建__init__()方法,或者__init__()方法只有一个self参数时,parameterlist可以省略。
(1)创建__init__()方法
在创建类后,可以手动创建一个__init__()方法。该方法是一个特殊的方法,每当创建一个新实例时,python都会自动执行它。__init__()方法必须包含一个self参数,并且必须是第一个参数。self参数是一个指向实例本身的引用,用于访问类中的属性和方法。在方法调用时会自动传递实际参数self,因此当__init__()方法只有一个参数时,在创建类的实例时,就不需要指定实际参数了。
注: 在__init__()方法中,除了self参数外,还可以自定义一些参数,参数间使用“,”进行分隔。
3.创建类的成员并访问
类的成员主要由实例方法和数据成员组成。在类中创建了类的成员后,可以通过类的实例进行访问。
(1)创建实例方法并访问
实例方法是指在类中定义的函数。语法格式如下:
def functionName(self,parameterlist):
block
参数说明:
block:方法体,实现的具体功能。
注:实例方法和python中的函数的主要区别就是,函数实现的是某个独立的功能,而实例方法是实现类中的一个行为,是类的一部分。
实例方法创建完成后,可以通过类的实例名称和点(.)操作符进行访问,语法格式如下:
instanceName.functionName(parametervalue)
参数说明:
instanceName:为类的实例名称。
functionName:为要调用的方法名称。
parametervalue:表示为方法指定对应的实际参数,其值的个数与创建实例方法中parametervalue的方法相同。
(2)创建数据成员并访问
数据成员是指在类中定义的变量,即属性,根据定义的位置,又可以分为类属性和实例属性。
类属性是指定义在类中,并且在函数体外的属性。类属性可以在类的所有实例之间共享值,也就是在所有实例化的对象中公用。
类属性可以通过类名称或者实例名访问。
注:实例属性是指定义在类的方法中的属性,只作用于当前实例中。
(3).访问限制
在类的内部可以定义属性和方法,而在类的外部则可以直接调用属性或方法来操作数据,从而隐藏了类内部的复杂逻辑。但是python并没有对属性和方法的访问权限进行限制。为了保证类内部的某些属性或方法不被外部所访问,可以在属性或方法名前面添加单下划线(_ears)、双下划线(__ears)或首尾加双下划线(_ears_),从而限制访问权限。其中,单下划线、双下划线、首尾双下划线的作用如下:
1)首尾双下划线表示定义特殊方法,一般是 系统定义名字,如_init_()。
2)以单下划线开头的表示protected(保护)类型的成员,只允许类本身和子类进行访问,但不能使用“from module import*” 语句导入。
3)双下划线表示private(私有)类型的成员,只允许定义该方法的类本身进行访问,而且也不能通过类的实例进行访问,但是可以通过“类的实例名._类名__xxx”方式访问
注:私有属性不能直接通过实例名+属性名访问,可以在类的实例方法中访问,也可以通过“实例名._类名__xxx”方式访问
四.属性
(1)创建用于计算的属性
在python中,可以通过@property(装饰器)将一个方法转换为属性,从而实现用于计算机的属性。将方法转换为属性后,可以直接通过方法名来访问方法,而不需要再添加一对小括号“()”,这样可以让代码更加简洁。
语法格式如下:
@property
def methodname(self):
block
参数说明:
methodname:用于指定方法名,一般使用小写字母开头。该名称最后将作为创建的属性名。
self:必要参数,表示类的实例。
block:方法体,实现的具体功能。在方法体中,通常以return语句结束,用于返回计算结果。
(2)为属性添加安全保护机制
在python中,默认情况下,创建的类属性或者实例是可以在类体外进行修改的,如果想要限制其不能在类体外进行修改,可以将其默认为私有的,但设置为私有后,在类体外也不能获取它的值。如果想要创建一个可以读取但不能修改的属性,那么可以使用@property实现只读属性。
五.继承
1.继承的基本语法
在python中,可以在类定义语句中,类名右侧使用一对小括号将要继承的基类名称括起来,从而实现类的继承。具体的语法格式如下:
class ClassName(baseclasslist):
'''类的帮助信息'''
statement
参数说明:
ClassName:用于指定类名。
baseclasslist:用于指定要继承的基类,可以有多个,类名之间用逗号“,”分隔。如果不指定,将使用所有python对象的根类目录object。
''类的帮助信息''':用于指定类的文档字符串,定义该字符串后,在创建类的对象时,输入类名和左侧的括号“(”后,将显示该信息。
statement:类体,主要由类变量(或类成员)、方法和属性等定义语句组成。如果在定义类时,没想好类的具体功能,也可以在类体中直接使用pass语句代替
2.方法重写
基类的成员都会被派生类继承,当基类中的某个方法不完全适用于派生类时,就需要在派生类中重写父类的这个方法。在上例中,基类中定义的harvest()方法,无论派生类是什么水果都显示“水果......”,如果想要针对不同水果给出不同的提示,可以在派生类中重写harvest()方法
3.派生类中调用基类的__init__()方法
在派生类中定义__init__()方法时,不会自动调用基类的__init__()方法。例如,定义一个Fruit类,在__init__()方法中创建类属性color,然后在Fruit类中定义一个harvest()方法,在该方法中输出类属性color的值,再创建继承自Fruit类的Apple类,最后创建Apple类的实例,并调用harvest()方法,代码如下:
执行上面的代码后,会出现异常情况。
因此,要让派生类调用基类的__init__()方法进行必要的初始化,需要在派生类使用super()函数调用基类的__init__()方法。因此,需要在上述代码的第8行代码的下方添加以下代码: