Python核心编程与应用 课件 【ch07】面向对象程序设计_第1页
Python核心编程与应用 课件 【ch07】面向对象程序设计_第2页
Python核心编程与应用 课件 【ch07】面向对象程序设计_第3页
Python核心编程与应用 课件 【ch07】面向对象程序设计_第4页
Python核心编程与应用 课件 【ch07】面向对象程序设计_第5页
已阅读5页,还剩51页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

Python核心编程与应用面向对象程序设计第七章新工科·数据科学与大数据系列01类与对象类与对象01类的定义类的定义语法格式如下:class类名(继承的父类列表):语句说明:class,定义类的关键字;类名,符合标识符规则的名称,约定首字母大写;继承的父类列表,该类继承的父类;语句,类的相关定义语句。类与对象01类的定义【例7-1】定义MyClass类。classMyClass(object):passmc=MyClass()

#实例化对象print(MyClass)print(mc)运行结果:<class'main.MyClass'>__main_.MyClassobjectat0x03355EB0>在“classMyClass(object)”中,MyClass是一个自定义的类,obiect是Python中所有对象的超类。这个自定义的类与系统类型(如imt、float)类似,都是抽象概念。类与对象01实例变量对dog1、dog2两只小狗分别取名“球球”“圆圆”,只要设置实例属性name即可。在Python中,每个实例都可以有自己的多个属性,实例的属性是个变量,因此也被称为实例变量,通常用来记录实例对象的相关信息。实例变量的使用方法如下:实例.变量名当首次为实例变量赋值时,就创建此实例变量,后续再次给实例变量赋值,则改变变量的绑定关系,即修改实例变量的值。类与对象01实例变量【例7-3】添加实例变量。classDog:passdog1=Dog()doglname=球球dogl.kinds=京巴dogl.color=白色dog1.color=黄色

#修改实例的值dog1.age=1类与对象01实例变量dog2=Dog()='圆圆'dog2kinds=拉布拉多dog2.color=棕色print(dog1.__dict)print(dog2.__dict__)运行结果:{'name':'球球','kinds':京巴,'color':黄色,'age':1}{'name':'中圆圆','kinds':'拉布拉多','color':'棕色'}内置属性dict用键值对的形式显示该对象的所有变量和值。dog1和dog2两个对象有各自的变量,可以给变量赋值,也可以修改变量的值。实例变量、对象的变量、对象的属性都是指同一回事。类与对象01实例方法实例方法是定义对象的动态行为,语法形式如下class类名(继承列表):def实例方法名(self,参数1,参数2,···):···文档字符串···语句块作用:描述一个对象的行为。说明:实例方法的定义类似函数定义,区别在于,第一个参数必须是self,代表对象实例自身;实例方法需要借助对象才能调用,调用格式为:实例.实例方法名(调用参数)类与对象01实例方法【例7-5】实例方法的定义及调用。classDog(obiect):defeat(self,food):

#定义实例方法eatprint(小狗正在吃,food)defsleep(self,hour):

#定义实例方法sleepprint(小狗睡了轻,hour,小时)d=Dog()d.eat('骨头')

#调用实例方法eatd.sleep(1)

#调用实例方法sleep运行结果小狗正在吃骨头小狗睡了1小时在调用实例方法时,参数self不需要值传递。02属性和方法属性和方法02通过函数操作属性对象的属性可以用赋值的方法绑定,如dogl.color=‘白色’,然后可以访问对象的属性print(dog1.color),还可以通过内建函数对属性进行更多的操作。①判断对象是否具备某属性:hasattr()。②新建对象的属性:setattr()。③提取对象的某属性的值:getattr)。④删除对象的某属性:delattr()。属性和方法02初始化方法上述设置对象属性的方法,不管是直接赋值还是通过函数操作新建属性或删除属性,都只是对某具体对象进行操作,或者是对某单独对象进行操作,若想对所有的新建对象统一设置属性,那么用类特有的方__init__,称为初始化方法。作用:对新创建的对象添加多个属性,并赋初始值。初始化方法的语法格式如下:class类名(继承列表):def_init_(self[,参数列表]):语句块初始化方法的调用规则如下:①初始化方法名必须为__init__,不可改变。②初始化方法会在构造函数创建实例后自动调用,并将自身通过参数self传入_init_。③构造函数的实参将通过__init__方法的参数列表传入该方法。④初始化方法中如果需要retumn语句返回,则只能返回None。属性和方法02析构方法析构方法是初始化方法的逆向操作,用于在销毁对象前释放该对象占用的资源。其实在Python中不需程序员编写析构方法,系统有自动垃圾回收功能。析构方法的语法格式如下:cLass类名(继承列表):def__del_(self):语句块说明:析构函数在对象被销毁时自动调用,析构函数调用的时间由解释器执行决定。属性和方法02内置实例属性(1)__dict__属性__dict__用键值对的形式显示该对象的所有属性。对__dict__字典中元素的操作等同于操作对象的属性。【例7-10】__dict__属性举例。classDog(object):passd=Dog()print(d.__dict__)

#运行结果:{}d.kinds='拉布拉多'print(d.__dict__)

#运行结果:{'kinds':'拉布拉多'd.color='白色'print(d.__dict__)

#运行结果:{'kinds':'拉布拉多','color':'白色'}print(d.__dict__['kinds'])

#运行结果:拉布拉多属性和方法02内置实例属性(2)__class__属性__class__属性用于获取一个对象所属的类。[例7-11]class属性举例。classDog(object):passd1=Dog()print(d1.__class__)

#d1对象所属的类为Dogd2=d1.__class__()

#执行构造函数,等同于d2=Dog()print(d2)

#d2是对象实例print(d2.__class__)

#d2对象所属的类为Dog运行结果:<class

'__main__.Dog'><_main_.Dog

object

at0x0000021639207040><class

'__main__.Dog'>属性和方法02用于类的函数isinstance(object,class_or_tuple)用于判断对象是否属于某个类,或者属于某个类型元组中的一个。type(object)用于返回对象的类型【例7-12】isinstance()函数和type()函数举例。classStudent(object):passprint(type(Student))

#运行结果:<classtype>,即class类型stu=Student()print(isinstance(stu,Student))

#运行结果:Trueprint(isinstance(3.14,(bool,int,float)))

#运行结果:Trueisinstance(3.14.(bool,int,float))用于判断3.14是否为类型元组(bool,int,fat)中的一个。03访问限制访问限制03受保护的属性(1)“_”开头为受保护的属性在类内部,有些属性是受保护的,不建议用户访问,但是也不是强制不能访问,为了给用户一个提醒,访问时通过“_”开头加以区分。(2)“__”开头的私有属性在类内部,有些属性限定是私有的,此时不允许用户从外部访问。实现方法是用“__”开头。私有属性可以通过特殊的语法实现访问,但是有可能不是对象实例中的原属性空间,因此不建议使用。私有属性安全性要求比较高,一般不对外暴露。访问限制03受保护的属性(3)通过方法访问私有属性classStudent(object):def__init__(self,name):=nameself.__age=18defget_age(self):

#定义getage方法访问私有属性returnself.__agedefset_age(self,age):

#定义setage方法if0<=age<=100:

#输入有效性限制self._age=age访问限制03受保护的属性s=Student('xiaoming')s.set_age(18)print(s.get_age())

#运行结果:18在类的内部,读取年龄的get_age方法和设置龄的set_age方法都可以访问私有变量__age,而get_age和set_age方法是公开的,可以在类外访问,所以通过公开的方法访问到了私有的属性__age。访问限制03属性装饰器对象的属性经常会遇到类似getage和setage方法的操作,即对属性的读和写两种操作Python通过装饰器把读和写进一步简化,把它们伪装成属性,以属性的形式对外提供接口,这就是属性装饰器。通过属性装饰器,在类外部以普通属性的形式访问内部的函数。只读属性使用@property,读写属性使用@属性名setter。访问限制03类的__slots__属性setattr()函数(见7.2)节可以新建对象的属性意味着对象的属性可以无限制地增加,类的slots属性正是要限定属性的随意增加,规定一个类创建的实例只能有固定的属性,不允许对象添加__slots__列表以外的属性。说明:①slots属性是一个列表,列表的值是字符串;②含有slots属性的类,创建的对象实例没有dict属性。访问限制03实例私有方法属性有私有属性,方法也有私有方法。类内部定义了私有方法后,该方法就不允许在类外部使用,即私有方法只能在类内部访问或调用。这样达到了隐藏的目的。定义私有方法只要在方法名前面加“__”如__set_name就成了私有方法。访问限制03类变量类变量是类的属性,属于类,不属于实例,被类内的所有实例共用。类变量可以通过类直接访问,也可以通过该类的对象实例访问,还可以通过该类的对象的__class__方法访问。【例7-18】类变量举例。classPerson(object):totalcount=0

#类变量def__init__(self,name):=nameself.__class__.total_count+=1print(Person.total_count)

#运行结果:0Person('xiaoming')print(Person.total_count)

#运行结果:1Person('leguan')print(Person.total_count)

#运行结果:2访问限制03类方法类方法是操作类的方法,属于该类。类方法需要使用@classmethod装饰器装饰。类方法的第一个参数是类,约定写成cs。类和对象实例都可以调用类方法,类方法中不能访问具体对象的属性。【例7-19】类方法举例。classStudent(object):count=0

#类变量@classmethod#装饰器defget_count(cls):

#类方法,第一个参数约定为cLsreturncis.count@classmethod#装饰器defsetcount(cls,value):

#类方法cls.count=valueprint(Student.getcount())

#运行结果:0,通过类调用类方法Student.setcount(10)print(Student.get_count())

#运行结果:10访问限制03静态方法静态方法是定义在类的内部的函数,其作用域是类的内部,与类方法相似,类和对象实例都可以调用该方法。区别在于,静态方法需要使用@staticmeehod装饰器装饰,不需要传入self参数或cls参数。凡需要访问类成员时则用类方法,若此方法与类成员毫无关系,则用静态方法。但是,静态方法不能访问类变量和属性。类和实例对象都可以调用实例方法、类方法、静态方法。只是实例方法由对象调用,至少有一个self参数,执行实例方法时,自动将调用该方法的对象赋值给self。类方法至少有一个cls参数,执行类方法时,自动将调用该方法的类赋值给cls。静态方法无默认参数。这三种方法的不同点在于方法的调用者不同、调用方法时自动传入的参数不同。04属性管理器属性管理器04反射的概念反射就是根据名称动态获取对象实例,一下子不容易理解,我们先从简单的例子开始。【例7-21】函数与字符串的区别。deffunc():print(func是这个函数的名字)print(ifunc')#运行结果’func'print(func)#运行返回函对象func的地址:<functionfuncat@x000002B78A0DBCA0>虽然都是fumc,但第一个print(func)中的func是字符串,第二个print(func)中的func0)是函数,类型不同,运行结果完全不同。这里使用了相同的名字func,下面进一步说明。属性管理器04动态导入模块Python内置的import(字符串参数)函数可以动态导入模块,实现类似getattr()函数的反射功能,会根据字符串参数,动态地导入同名的模块。【例7-25】重写visispy文件,动态导入模块myshop。'''visit.py'''defrun():inp=input('请输入您想访问的页面:').strip()modules,func=inp.split("/")

#此处modules和func是宇符串obj=__import(modules)

#obi是模块ifhasattr(obj,func):func=getattr(obj,func)func()属性管理器04动态导入模块else:print('404')if__name__=='__main__':run()运行时输入:myshop/login返回:用户登录输入“myshop/login”程序会动态地导入myshop模块;输入“mysite/login”,则动态地导入mysite模块。语句“modules,func=inpsplit("/")”实现了用户输入字符的动态拆分,以“/”为分隔符,拆分成了模块名和方法名,然后用__import__(modules)导入该模块。05封装与集成封装与集成05封装函数是一种封装,把实现特定功能的代码单独提取出来,取一个名字作为函数名,可以作为独立的单位来调用。函数的封装是对一段代码的封装。类是比函数更高级的封装,把函数和变量封装在一起,称为类的方法和属性,隐藏在类内用类表达一个抽象的概念。所以,面向对象程序设计中的封装是指将数据与具体操作的实现代码存放在对象内部,使这些代码的实现细节隐藏起来,不被外界发现,外界也不能通过任何形式修改对象内部的操作,外界只能通过接口使用该对象。有了封装机制,程序在使用某对象时不需要关心该对象的数据结构细节及实现操作的方法。这样不仅使代码更易维护,还在一定程度上保证了系统的安全性。封装与集成05继承继承来源于现实世界,如孩子会继承父母的遗传基因。面向对象程序设计中的继承机制最关键的功能是实现代码的复用。例如,有两个子类,发现它们有很多共同的特征和行为,那么把它们的共同部分提取出来,放在新的类中,这个新的类就是它们的父类,自然两个子类继承了父类的所有功能。所以,多个类公用的代码可以只在一个类中提供,其他类只需要继承这个类即可,继承的类称为子类(subclass),被继承的类称为基类、父类或超类(Baseclass、Superclass)。封装与集成05继承子类在获得父类的全部变量和方法的同时,还可以根据需要进行修改和拓展。其语法格式如下:classFoo(superA,superb,superC,···):Python支持多父类的继承机制,需要注意“()”中基类的顺序,这决定了所要调用的方法的查找顺序。先在子类Foo中找,若没找到,则从左至右顺序找superA、superb、superC、···深度优先搜索这些基类中是否包含该方法。一旦找到,则直接调用,停止继续查找;若都没找到,则抛出异常。封装与集成05继承1.Python3的继承机制子类在调用某个方法或变量的时候,先在自己内部查找,如果没有找到,就在父类里查找根据父类定义中的顺序,以深度优先的方式逐一查找父类。2.super()函数在子类中,如果有与父类同名的成员,就会覆盖父类中的成员,即子类优先。如果想强制调用父类的成员,可以使用super()函数,这是一个非常重要的函数,最常见的就是通过super调用父类的初始化方法_init_。super()函数的语法格式如下:super(子类名,self).方法名()需要传入的是子类名和self,调用的是父类的方法,因此方法名后需要按父类的方法传入参数。06函数重写函数重写06函数重写函数重写是让自定义类生成的对象实例像内建对象一样进行内建函数操作。【例7-35】函数重写。#重写前classMyClass:passobj=MyClass()print(len(obj))运行后报错:TypeError:objectoftype

'MyClass'hasnolen()因为用len()函数计算一个自定义类的对象实例的长度,系统不知道怎么做,自定义类内也没有说明,那么需要重写__len__方法。函数重写06函数重写#重写后classMyClass:def__len__(self):return100obj=MyClass()print(len(obj))运行结果:100因为重写len方法时固定返回长度100。上面的例子尽管重写了len()函数,但没有体现出任何的实际意义。函数重写06常用内建函数重写常用内建函数如表7-1所示。函数重写06常用内建函数重写【例7-39】重写str()len()、abs()函数,求自定类MyList对象的长度和绝对值。classMylist:def__init_(self,iterable=None):ifiterable==None:iterable=[]self.data=[xforxiniterable]def__str_(self):return"MyList(%s)"self.datadef__len__(self):returnlen(self.data)def__abs__(self):returnMylist((abs(x)forxinself.data))函数重写06常用内建函数重写L=Mylist([1,-2,3,-4])print(L.data)print(len(L))print(abs(L).data)运行结果:[1,-2,3,-4]4[1,2,3,4]MyList([1,-2,3,-4])取绝对值后的结果是MyList12,3,4]),这就是abs)函数重写的具体体现。原始的内建函数abs),若写成:abs([1,-2,3,-41]]则直接报错:badoperandtypeforabs():‘list’函数重写06数值转换函数重写数值转换函数的重写主要是将自定义类型创建的对象转换为系统内建的数据类型。能重写的数值转换函数有如表7-2所示。函数重写06数值转换函数重写【例7-40】数值转换函数重写。classMyNumber:def__init__(self,value):self.data=valuedef__int__(self):returnint(selfdata)def__float_(self):returnfloat(self.data)def__bool__(self):returnbool(int(self.data))n1=MyNumber(‘100’)print(int(n1))函数重写06数值转换函数重写print(float(n1))print(complex(n1))print(bool(n1))运行结果:100100.0(100+0j)Truecomplex()函数重写说明:取__omplex(self)方法的返回值作为结果返回,若自定义对象没有complex(self)方法,就会用__float__(self)方法返回值作为实部,用0j作为虚部返回若没有__foat__(obj)方法,就会触发TypeError类型的错误并进入异常状态。07运算符重载运算符重载07算术运算符算术运算符有7个,是双目运算,如表7-3所示,运算时有正向和反向之分,如a-b和b-a的含义完全不同。正向算术运算符表示从对象自身出发加上右侧的另一个操作对象,方法__add__(self,rhs)表示self+rhs。运算符重载07复合赋值运算符重载复合赋值算术运算符也有7个,如表7-5所示。复合赋值算术运算符重载规则:以复合赋值算术运算符x+=y为例,此运算符会优先调用x.__iadd__(y)方法如果没有,那么将复合赋值运算拆解为x=x+y,再调用x=x.__add__(y)方法,如果还找不到,就触发TypeError异常。其他复合赋值算术运算符也具有相同的规则。运算符重载07比较运算符重载比较运算符(如表7-6所示)的重规则与算术运算符的重载规则一致。比较运算符重载通常返回布尔值True或False。08多态和枚举类多态和枚举类08多态多态是面向对象程序设计中最核心和最关键的技术。Python的多态性是指具有不同功能的函数可以使用相同的函数名,这样就可以用一个函数名调用不同内容

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论