Python程序设计第8章-程序开发进阶课件.pptx
- 【下载声明】
1. 本站全部试题类文档,若标题没写含答案,则无答案;标题注明含答案的文档,主观题也可能无答案。请谨慎下单,一旦售出,不予退换。
2. 本站全部PPT文档均不含视频和音频,PPT中出现的音频或视频标识(或文字)仅表示流程,实际无音频或视频文件。请谨慎下单,一旦售出,不予退换。
3. 本页资料《Python程序设计第8章-程序开发进阶课件.pptx》由用户(三亚风情)主动上传,其收益全归该用户。163文库仅提供信息存储空间,仅对该用户上传内容的表现方式做保护处理,对上传内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知163文库(点击联系客服),我们立即给予删除!
4. 请根据预览情况,自愿下载本文。本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
5. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007及以上版本和PDF阅读器,压缩文件请下载最新的WinRAR软件解压。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Python 程序设计 程序 开发 进阶 课件
- 资源描述:
-
1、2022-6-9第第8章章 程序开发进阶程序开发进阶目录目录2022-6-928.1. 面向对象程序开发进阶8.2. 函数式编程8.3. 多线程编程2022-6-98.1 面向对象程序设计进阶在这一节中,我们将更深入地学习Python对面向对象的支持,学习一些技术以合理减少必须编写的代码总量,并扩展程序功能。2022-6-98.1 面向对象程序设计进阶8.1.1 控制属性存取有时候,类属性的值在运算时被计算出来要比预先存储更加方便,下面给出一个这种类的完整实现。 class Ord:def _getattr_(self, char):return ord(char) ord()是以个Pytho
2、n内置函数,返回代表一个Unicode字符的数字值。当Ord类被定义后,我们可以创建一个实例,ord = Ord(),这样我们就得到了内置ord()函数的替代品。例如,ord.a返回97,ord.A返回65。(但ord.!以及类似的用法会出现语法错误。)2022-6-98.1 面向对象程序设计进阶8.1.1 控制属性存取如果直接在Python运行环境,如IDLE中输入Ord类的定义,之后试图执行ord = Ord(),则不能正确工作。这是因为实例与Ord类中使用的ord()内置函数重名,因此,ord()调用实际上变成了对ord实例的调用,并导致TypeError异常。但如果我们引入包含Ord类
3、的模块,则不会出现这个问题。因为交互式创建的ord对象与Ord类使用的ord()函数分别存在于两个模块中,彼此不会互相替代。如果我们确实要交互式地创建一个类并需要重用某个内置对象的名称,就必须确保该类调用的是内置对象,这里可以通过导入builtins模块来提供对所有内置函数无歧义的访问。在代码中调用builtins.ord()来替代ord()。2022-6-98.1 面向对象程序设计进阶8.1.2 函子在计算机科学中,函子(Functor)是指一个对象,该对象可以像普通的函数一样被调用。由于Python的函数本身就是对象,所以在Python中,函子可以被理解为另外一种函数对象。任何含有_cal
4、l()_特殊方法的类都是函子。使用函子的主要好处是,可以维护一些状态信息。我们也可以用普通函数完成同样的任务,但如果我们同时需要存储一些状态信息,或者进行更复杂的处理,函子通常是正确的选择2022-6-98.1 面向对象程序设计进阶8.1.2 函子下面创建了一个函子,功能是除去字符串末尾的基本标点符号。其创建和使用格式如下。strip_punctuation = Strip(,;:.!?)strip_punctuation(whoops!) #返回: whoops 这里我们创建了一个Strip函子的实例,并用值“,;:.!?”将其初始化。当这个实例被调用时,都会返回作为参数的字符串,并除去其末
5、尾的标点符号。下面给出Strip类的完整实现。class Strip:def _init_(self, characters):self.characters = charactersdef _call_(self, string):return string.strip(self.characters)。2022-6-98.1 面向对象程序设计进阶8.1.3 上下文管理器使用上下文管理器(Context Manager)可以简化代码,这是通过确保某些操作在特定代码块执行前与执行后再进行来实现的。之所以能实现这种操作,是因为上下文管理器定义了两个特殊的方法_enter_()和_exit_(),
6、在with语句的范围类,Python会对其进行特别处理。当一个上下文管理器在with语句中创建时,它的_enter_()方法会自动被调用。当上下文管理器超出其作用范围时,到了with语句之外时,其_exit_()方法将自动被调用。2022-6-98.1 面向对象程序设计进阶8.1.3 上下文管理器我们可以自定义上下文管理器,或者使用预定义的上下文管理器。调用内置的open()函数所返回的文件对象就是上下文管理器。使用上下文管理器的语法如下: with expression as variable:suite2022-6-98.1 面向对象程序设计进阶8.1.4 描述符描述符(Descripto
7、r)也是类,用于为其他类的属性提供访问控制。实现了一个或多个描述符特殊方法(例如_get_(),_set_()和_delete_())的任何类都可以被称为(也可以用作)描述符。内置的property()与classmethod()函数都是使用描述符实现的。理解描述符的关键是:尽管在类中创建描述符的实例时将其作为一个类属性,但是Python在访问描述符时是通过类的实例进行的。2022-6-98.1 面向对象程序设计进阶8.1.4 描述符假定有一个类,其实例存放一些字符串。并且需要的时候可以获取字符串的XML转义处理后的版本。此处创建一个描述符,以便根据需要提供XML转义处理后的字符串,而又不需要
8、对其进行存储。描述符的类如下: class Product:_slots_ = (_name, _description, _price)name_as_xml = XmlShadow(name)description_as_xml = XmlShadow(description) def _init_(self, name, description, price):self._name = nameself.description = descriptionself.price = price2022-6-98.1 面向对象程序设计进阶8.1.4 描述符现在考察另外一种描述符,该描述符可用于
9、存储某个对象的所有属性数据,对象本身则不再需要存储任何内容。在该实例中,我们仅使用一个字典来进行存储。下面给出使用了描述符修改后的Point类的开头。class Point:_slots_ = ()x = ExternalStorage(x)y = ExternalStorage(y) def _init_(self, x=0, y=0):self.x = xself.y = y 通过将slots设置为一个空元组,可以保证类不会存储任何数据属性。2022-6-98.1 面向对象程序设计进阶8.1.5 抽象基类抽象基类(Abstract Base Class)也是一个类,但这个类不能用于创建对象
10、。使用抽象基类的目的是为了定义接口(Interface)。抽象基类会列出一些方法与特性,而继承自抽象基类的类必须对其进行实现。这是种很有用的机制,因为我们可以将抽象基类当作一种保证,确保任何自抽象基类衍生而来的类均会实现抽象基类指定的方法与特性。抽象基类中包含至少一种抽象方法或特性,抽象方法在定义时可以不实现(其suite为pass,或者产生一个NotImplementedError异常,以强制子类对其重新实现),也可以包含具体的实现。抽象基类也可以包含其他具体的(非抽象)方法与特性。2022-6-98.1 面向对象程序设计进阶8.1.5 抽象基类只有在实现了所有继承而来的抽象方法与抽象特性之
11、后,从抽象基类衍生而来的类才可以创建实例。对与那些已经包含具体实现的抽象方法,衍生类可以简单地使用super()来调用基类的实现版本。与通常一样,任何具体方法与特性都可以通过继承获取。所有抽象基类必须包含元类(Metaclass)abc.ABCMeta(来自abc模块),或来自其某个子类。2022-6-98.1 面向对象程序设计进阶8.1.6 多继承多继承是指某个类继承自两个或多个类。Python完全支持多继承。多继承存在的问题是,可能导致同一个类被继承多次(比如一个类中某两个基类继承自同一个类)。这意味着,某个被调用的方法如果不在子类中,而是在两个或多个基类中(或基类的基类中),那么被调用方
12、法的具体版本取决于方法的解析顺序,从而使得使用多继承得到的类存在模糊的可能。2022-6-98.1 面向对象程序设计进阶8.1.6 多继承声明多继承的方式与单继承类似。 class Base1:pass class Base2:pass class MultiDerived(Base1, Base2):pass MultiDerived类继承自类Base1和Base2,并同时拥有这两个类的特性。为了保证多继承中调用方法的正确性,我们有必要考察Python中方法的解析顺序。2022-6-98.1 面向对象程序设计进阶8.1.6 多继承有一套规则用于找到类中方法的解析顺序,被称为方法解析顺序(MR
13、O),MRO保证一个类总是在它的基类之前出现。一个类的MRO可以通过_mro_属性或mro()方法查看,前者返回一个元组,后者返回一个列表: MultiDerived._mro_(,) MultiDerived.mro(),2022-6-98.1 面向对象程序设计进阶8.1.7 元类元类之于类,就像类之于实例。也就是说,元类用于创建类,正如类用于创建实例一样。元类最简单的用途就是自定义抽象基类,正如我们在前面所看到的那样。不同于很多编程语言,Python的类也是对象,当使用关键字class后,Python会执行它,并创建一个对象。下面的代码在内存中创建了一个名为“ObjectCreator”的
14、类。 class ObjectCreator(object): pass 这个类对象自身可以创建对象,即类的实例,但它本身是一个对象,所以我们可以对其进行赋值、添加属性或将其作为函数的参数。2022-6-98.1 面向对象程序设计进阶8.1.7 元类更进一步,我们能够动态创建类,就如同创建其他对象一样,我们可以用class关键字来创建类。 def choose_class(name): if name = foo: class Foo(object): pass return Foo else: class Bar(object): pass return Bar 2022-6-98.1 面向
15、对象程序设计进阶8.1.7 元类因为类也是对象,所以必定存在一个工具,用来创建类。当我们使用class关键字时,Python自动创建了对象,但正如许多Python的其他特性,有一种方法也可以让我们手动创建这个对象。type()函数有一种完全不同的功能,即可以动态地创建类。我们可以将类的描述作为参数传递给type()函数,然后得到一个类的返回值。 所以,类: class MyClass(object): bar = True 可以用以下的方式创建。 MyClass = type(MyClass , (), bar:True) 目录目录2022-6-928.1. 面向对象程序开发进阶8.2. 函数
16、式编程8.3. 多线程编程2022-6-98.2 函数式编程函数是Python内建支持的一种封装,我们通过把大段代码拆成函数,通过一层一层的函数调用,就可以把复杂任务分解成多个简单的任务,这种分解可以称之为面向过程的程序设计。函数就是面向过程的程序设计的基本单元。函数式编程(Functional Programming),其思想更接近数学计算,抽象度较高。函数式编程就是一种抽象程度很高的编程范式,纯粹的函数式编程语言编写的函数没有变量,因此,对任意一个函数,只要输入是确定的,输出就是确定的。而允许使用变量的程序设计语言,由于函数内部的变量状态不确定,同样的输入,可能得到不同的输出,因此,这种函
17、数是有副作用的。函数式编程的一个特点就是,允许把函数本身作为参数传入另一个函数,甚至还允许返回一个函数。2022-6-98.2 函数式编程8.2.1 高阶函数要理解高阶函数(Higher-order function),首先要对Python中的函数概念有正确的理解。由于Python中一切都是对象,所以可以让一个变量指向函数。在Python中,我们不仅可以把函数调用的结果赋值给变量,也可以把函数本身赋值给变量。 f = abs f 然后通过这个变量来调用函数: f(-10)102022-6-98.2 函数式编程8.2.1 高阶函数变量可以指向函数,函数的参数能接收变量,那么一个函数就可以接收另一
18、个函数作为参数,这种函数就称之为高阶函数。一个简单的高阶函数代码如下。 def add(x, y, f):return f(x) + f(y) 当我们调用add(-2, 6, abs)时,参数x,y和f分别接收-2,6和abs,根据函数定义,我们知道实际的计算为:abs(-2)+abs(6) =2+6=8。可以输入以下代码进行验证。 add(-2, 6, abs)82022-6-98.2 函数式编程8.2.2 闭包通常我们把定义在一个函数里的函数称为嵌套函数,下面是一个简单嵌套函数的定义。 def print_msg(msg):This is the outer enclosing funct
19、ion def printer():This is the nested functionprint(msg) returnprinter 2022-6-98.2 函数式编程8.2.2 闭包我们将嵌套的printer函数作为返回值返回,然后我们尝试调用这个函数。 f = print_msg(Hello) f()Hello print_msg()函数被调用,并接收参数“Hello”,返回的函数被赋值给f。当我们调用f()时,传入的参数“Hello”仍然被保存着,即使print_msg()函数的执行已经结束。在外部函数( Enclosing Function)作用域里的数据“Hello”,即便在超
20、出作用域后仍然被保存着。这种把某些数据与函数关联在一起的技术在Python中被称为闭包(Closure)。 2022-6-98.2 函数式编程8.2.2 闭包创建一个闭包所需要具备的条件:必须有一个嵌套函数。嵌套函数必须应用一个在外部函数中定义的值。外部函数必须将嵌套函数作为返回值返回。闭包可以提供一些数据隐藏的方式,也可用来减少全局数据的使用。另外,闭包为一些问题提供了更符合面向对象思想的解决方案。2022-6-98.2 函数式编程8.2.3 匿名函数当我们传入函数作为参数时,有些时候并不需要显式地定义函数,直接传入匿名函数更方便。匿名函数在Python中被称为lambda函数。在Pytho
21、n中,对匿名函数提供了有限的支持。还是以map()函数为例,为了计算f(x)=x2,除了定义一个f(x)的函数外,还可以在参数中直接传入匿名函数: list(map(lambda x: x * x, 1, 2, 3, 4, 5, 6, 7, 8, 9)1, 4, 9, 16, 25, 36, 49, 64, 81 2022-6-98.2 函数式编程8.2.3 匿名函数关键字lambda表示匿名函数,冒号前面的x表示函数参数。使用匿名函数会受到一些限制,只能有一个表达式,但也不用写return,返回值就是该表达式的结果。因为函数没有名字,匿名函数也带来一个好处:不必担心函数名冲突。此外,匿名函数
展开阅读全文