第十天 第七章 面向对象程序设计
# 类是封装对象的属性和行为的载体,即具有相同属性和行为的一类实体被称为类。 # 面向对象设计程序设计的三大特点:封装、继承、多态 # 一、封装是面向对象编程的核心思想,将对象的属性和行为封装起来,其载体就是类,类会对客户隐藏其实现细节,这就是封装的思想 # 采用封装思想保证了类内部数据结构的完整性,提高了程序的可维护性 # 二、继承是实现重复利用的重要手段,子类通过继承父类的属性和行为的同时又添加了子类特有的属性和行为 # 三、将父类对象应用于子类的特征就是多态, # python中,类表示具有相同属性和方法的对象集合。在使用类时需要先定义类,然后再创建类的实例,通过实例可以访问类中的属性和方法 # 定义类用class关键字实现 class Geese: # ClassName是自定义的类名,一般用驼峰式命名法 '''大雁类''' # 指定类的文档字符串,使用该类时会显示帮助信息 pass # 类体,主要由类变量(也称类成员)、方法和属性等定义语句组成 # 创建类的实例,即实例化该类的对象: # obj = ClassName(parameterlist) # obj:用类创建的实例化对象 # ClassName:类名 # parameterlist:可选参数,如果该类没有__init__()方法,或__init__()方法只有一个self参数时可以省略 wildGoose = Geese() print(wildGoose) # 显示<__main__.Geese object at 0x00000161D9AA87C0> 说明wildGoose是一个Geese类的实例 # __init__()方法是一个特殊的方法,每建立一个新实例时会自动执行它,这个方法必须包含一个self参数,并且必须是第一个参数 # self参数是一个指向实例本身的引用,用于访问类中的属性和方法,在方法调用时会自动传递实际参数self # 因此当__init__()方法只有一个参数时,在创建类的实例时,就不需要指定实际参数了 class Bird: '''鸟类''' def __init__(self): print('我是鸟类') birdOne = Bird() # 自动输出“我是鸟类” # __init__()方法中,除了self参数外,还可以自定一些参数,参数间用逗号隔开 class Person: '''人类''' def __init__(self,weight,height,eat): print('我是人类,我有以下特征') print(weight) print(height) print(eat) weight_1 = '我有自己的体重' height_1 = '我有自己的身高' eat_1 = '我可以吃东西' aPerson = Person(weight_1,height_1,eat_1) # 创建类的成员并访问 # 1、创建实例方法并访问:实例方法是指在类中定义的函数,第一个参数必须是self,并且必须包含一个self参数 def functionName(self,parameterlist): pass # functionName:方法名,一般用小写字母开头 # self:必要参数,表示类的实例,可以是其它单词,使用self只是一个惯例而已 # parameterlist:用于指定除self参数以外的参数,多个参数用逗号隔开 # pass:方法体,实现的具体功能 # 实例方法创建完成后,可以通过类的实例名和点操作符进行访问:类名.方法名(参数) # 在Geese类中定义一个fly(self,state)方法 def fly(self,state): print(state) # 调用时就可以这么调用:wildGoose.fly('我会飞行') # 实例方法也可以有默认参数,但默认参数必须放在所有普通参数的最后:def fly(self, state='我会飞行') # 调用时就可以不用指定参数,而可以直接使用wildGoose.fly()即可 # 2、创建数据成员并访问:数据成员是指在类中定义的变量,即属性,根据定义位置又可以分为类属性和实例属性 class Geese: '''雁类''' neck = "脖子较长" # 类属性(脖子) wing = "振翅频率高" # 类属性(翅膀) leg = "腿位于身份的中心支点,行走自如" # 类属性(腿) number = 0 # 编号 def __init__(self): # 构造方法 Geese.number += 1 # 将编号加1 print("\n我是第"+str(Geese.number)+"只大雁,我属于雁类!我有以下特征:") print(Geese.neck) # 输出脖子的特征 print(Geese.wing) # 输出翅膀的特征 print(Geese.leg) # 输出腿的特征 # 创建4个雁类的对象(相当于有4只大雁) list1 = [] for i in range(4): # 循环4次 list1.append(Geese()) # 创建一个雁类的实例 print("一共有"+str(Geese.number)+"只大雁") Geese.beak = "喙的基部较高,长度和头部的长度几乎相等" # 添加类属性,添加后所有实例都中可使用 print("第2只大雁的喙:",list1[1].beak) # 访问类属性 # 实例属性:定义在类的方法中的属性,只作用于当前实例 class Geese: '''雁类''' def __init__(self): self.neck='脖子较长' print(self.neck) # 只能用实例访问(self.neck),而不能用类名访问(Geese.neck会报错) geese = Geese() # 访问限制:为了保证内部的一些属性和方法不被外部访问,可以加单下划线、双下划线或首尾加双下划线 # 1、首尾加双下划线:表示定义特殊方法,一般是系统定义名字,如__init__() # 2、单下划线开头表示保护类型的成员,只允许类本身和子类进行访问,但不能使用“from module import *”导入 # 3、双下划线表示私有类型的成员,只允许定义该类的方法本身进行访问,而且也不能通过类的实例进行访问 # 可以通过“类的实例名._类名__xxx”访问,如: class Swan: '''天鹅类''' __neckSwan = '天鹅的脖子很长' def __init__(self): print('__init__():',Swan.__neckSwan) swan = Swan() print('加入类名:',swan._Swan__neckSwan) # 可以通过“类的实例名._类名__xxx”访问 # print('直接访问:',swan.__neckSwan) # 出错,直接访问失败 # 属性:通过@property(装饰器)将一个方法转换为属性,从而实现用于计算的属性。转换后直接通过方法名访问,不用加小括号。 class Rect: def __init__(self,width,height): self.width = width self.height = height @property def area(self): return self.width*self.height rect = Rect(600,800) print('area is :',rect.area) # 注:@property转换后的属性不能重新赋值,如果重新赋值会抛出AttributeError异常。 # 在类中将属性或实例设置为私有(前面加双下划线),那么在类体外也不能通过实例名+属性名获取它的值,这时可以使用@property实现只读属性。 class Tvshow: def __init__(self, show): self.__show = show @property def show(self): return self.__show tvshow = Tvshow('now is play: <hello world>') print('default: ',tvshow.show) # 通过属性不仅可以将属性设置为只读属性,而且可以为属性设置拦截器,即允许对属性进行修改,但修改时需要遵守一定的约束。 # 继承:在程序中实现继承,表示这个类拥有它继承的类的所有公有成员或者受保护成员。 # 在面向对象编程中,被继承的类称为父类或基类,新的类称为子类或派生类。 class father: # 父类(基类) pass class ClassName(father): # 子类(派生类) '''类的帮助信息''' pass # 派生类中定义__init__()方法时,不会自动调用基类的__init__()方法。派生类中改为:super().__init__()