概述
函数
函数作为参数
函数
函数也是Python内置的一个高阶函数。reduce()函数接收的参数和 map()类似,一个函数 f,一个list,但行为和 map()不同,reduce()传入的函数 f 必须接收两个参数,reduce()对list的每个元素反复调用函数f,并返回最终结果值。
一个f函数,接收x和y,返回x和y的和:
函数
函数是 Python 内置的另一个有用的高阶函数,filter()函数接收一个函数 f 和一个list,这个函数 f 的作用是对每个元素进行判断,返回 True或 False,filter()根据判断结果自动过滤掉不符合条件的元素,返回由符合条件元素组成的新list。
一个list [1,4,6,7,9,12,17]中删除偶数,保留奇数,首先,要编写一个判断奇数的函数:
删除 s 字符串中开头、结尾处的 rm 序列的字符。
默认删除空白符(包括' ',' ',' ',' '),如下:
自定义排序函数
y:
调用 sorted() 并传入 reversed_cmp 就可以实现倒序排序:
函数
函数不但可以返回int、str、list、dict等数据类型,还可以返回函数!
函数内部定义的函数和外部定义的函数是一样的,只是他们无法被外部访问:
函数引用了外层函数的变量(参数也算变量),然后返回内层函数的情况,称为闭包(Closure)。
函数还引用了外层函数的局部变量,所以,要正确使用闭包,就要确保引用的局部变量在函数返回后不能变。举例如下:
调用f1(),f2()和f3()结果应该是1,4,9,但实际结果全部都是 9(请自己动手验证)。
函数返回了3个函数时,这3个函数所引用的变量 i 的值已经变成了3。由于f1、f2、f3并没有被调用,所以,此时他们并未计算 i*i,当 f1 被调用时:
函数
函数可以接收函数做参数,有些时候,我们不需要显式地定义函数,直接传入匿名函数更方便。
函数提供了有限支持。还是以map()函数为例,计算 f(x)=x2 时,除了定义一个f(x)的函数外,还可以直接传入匿名函数:
一个高阶函数,它接收一个函数作为参数,然后,返回一个新函数。
代码。
一个@log的定义:
函数首先返回一个decorator函数,再让这个decorator函数接收my_func并返回新函数:
调用会失败,因为在3层嵌套的decorator定义中,最内层的wrapper引用了最外层的参数prefix,所以,把一个闭包拆成普通的函数调用会比较困难。不支持闭包的编程语言要实现同样的功能就需要更多的代码。
函数功能的增加,但是,经过@decorator“改造”后的函数,和原函数相比,除了功能多一点外,有没有其它不同的地方?
函数名:
输出: f1
函数名:
输出: wrapper
函数函数名已经不是'f2',而是@log内部定义的'wrapper'。这对于那些依赖函数名的代码就会失效。decorator还改变了函数的doc等其它属性。如果要让调用者看不出一个函数经过了@decorator的“改造”,就需要把原函数的一些属性复制到新函数中:
函数的所有必要属性都一个一个复制到新函数上,所以Python内置的functools可以用来自动化完成这个“复制”的任务:
functools
functools.wraps(f)
函数签名改成了(args,*kw),因此,无法获得原函数的原始参数信息。即便我们采用固定参数来装饰只有一个参数的函数:
函数的参数名,因为新函数的参数名始终是 'x',原函数定义的参数名不一定叫 'x'。
functools.partial就是帮助我们创建一个偏函数的,不需要我们自己定义int2(),可以直接使用下面的代码创建一个新的函数int2:
文件系统中:
文件,每层都必须要有
错误:
代码先尝试从cStringIO导入,如果失败了(比如cStringIO没有被安装),再尝试从StringIO导入。这样,如果cStringIO模块存在,则我们将获得更快的运行速度,如果cStringIO不存在,则顶多代码运行速度会变慢,但不会影响代码的正常执行。
错误,并在捕获到指定错误时执行 except 语句。
属性
属性。
属性?由于Python是动态语言,对每一个实例,都可以直接给他们的属性赋值,例如,给xiaoming这个实例加上name、gender和birth属性:
属性
一个实例绑定各种属性,但是,现实世界中,一种类型的实例应该拥有相同名字的属性。例如,Person类应该在创建的时候就拥有 name、gender 和 birth 属性,怎么办?
添加一个特殊的init()方法,当创建实例时,init()方法被自动调用,我们就能在此为每个实例都统一加上以下属性:
方法常常忘记了 self 参数:
一个实例绑定很多属性,如果有些属性不希望被外部访问到怎么办?
属性权限的控制是通过属性名来实现的,如果一个属性由双下划线开头(__),该属性就无法被外部访问。看例子:
属性
一个实例上的属性不会影响其他实例,但是,类本身也是一个对象,如果在类上绑定一个属性,则所有实例都可以访问类的属性,并且,所有实例访问的类属性都是同一个!也就是说,实例属性每个实例各自拥有,互相独立,而类属性有且只有一份。
属性可以直接在 class 中定义:
属性只有一份,所以,当Person类的address改变时,所有实例访问到的类属性都改变了。
属性和实例实型名字冲突怎么办
修改类属性会导致所有实例访问到的类属性全部都受影响,但是,如果在实例变量上修改类属性会发生什么问题呢?
属性address ,对p1来说,它有一个实例属性address(值是'China'),而它所属的类Person也有一个类属性address,所以:
属性,返回'China'。
属性address,但是有类属性address,因此返回'Earth'。
属性和类属性重名时,实例属性优先级高,它将屏蔽掉对类属性的访问。
属性删除后,访问 p1.address 就又返回类属性的值 'Earth'了:
方法
一个实例的私有属性就是以__开头的属性,无法被外部访问,那这些属性定义有什么用?
属性无法从外部访问,但是,从类的内部是可以访问的。除了可以定义实例的属性外,还可以定义实例的方法。
方法就是在类中定义的函数,它的第一个参数永远是 self,指向调用该方法的实例本身,其他参数和一个普通函数是完全一样的:
@H_721_301@
方法也是属性
标记一个 @classmethod,该方法将绑定到 Person 类上,而非类的实例。类方法的第一个参数将传入类本身,通常将参数名命名为 cls,上面的 cls.count 实际上相当于 Person.count。
调用,而非实例上调用,因此类方法无法获得任何实例变量,只能获得类的引用。
父类类型,如果我们从 Person 派生出 Student和Teacher ,并都写了一个 whoAmI() 方法:
方法调用将作用在 x 的实际类型上。s 是Student类型,它实际上拥有自己的 whoAmI()方法以及从 Person继承的 whoAmI方法,但调用 s.whoAmI()总是先查找它自身的定义,如果没有定义,则顺着继承链向上查找,直到在某个父类中找到为止。
函数 who_am_i(x)的参数 x 不一定是 Person 或 Person 的子类型。任何数据类型的实例都可以,只要它有一个whoAmI()的方法即可:
一个父类继承外,Python允许从多个父类继承,称为多重继承。
功能。多重继承通过 super()调用init()方法时,A 虽然被继承了两次,但init()只调用一次:
功能使用。
方法
默认的比较函数 cmp 排序,但是,如果对一组 Student 类的实例排序时,就必须提供我们自己的特殊方法 cmp():
方法,cmp用实例自身self和传入的实例 s 进行比较,如果 self 应该排在前面,就返回 -1,如果 s 应该排在前面,就返回1,如果两者相当,返回 0。
一个类表现得像一个list,要获取有多少个元素,就得用 len() 函数。
函数工作正常,类必须提供一个特殊方法len(),它返回元素的个数。
一个 Students 类,把名字传进去:
一个Rational类来表示:
函数正常工作,只需要实现特殊方法float()。
score(1000) 就会报错。
方法来封装对一个属性的访问在许多面向对象编程的语言中都很常见。
score() 和 s.set_score() 没有直接写 s.score 来得直接。
方法?----有。
支持高阶函数,在函数式编程中我们介绍了装饰器函数,可以用装饰器函数把 get/set 方法“装饰”成属性调用:
一个score(self)是get方法,用@property装饰,第二个score(self,score)是set方法,用@score.setter装饰,@score.setter是前一个@property装饰后的副产品。
属性一样设置score了:
添加属性。
添加的属性,例如,Student类只允许添加 name、gender和score 这3个属性,就可以利用Python的一个特殊的slots来实现。
一个类允许的属性列表:
属性,如果不需要添加任意动态的属性,使用slots也能节省内存。
函数其实是一个对象:
调用:
一个父类继承外,Python允许从多个父类继承,称为多重继承。
功能。多重继承通过 super()调用init()方法时,A 虽然被继承了两次,但init()只调用一次:
功能使用。
方法
默认的比较函数 cmp 排序,但是,如果对一组 Student 类的实例排序时,就必须提供我们自己的特殊方法 cmp():
方法,cmp用实例自身self和传入的实例 s 进行比较,如果 self 应该排在前面,就返回 -1,如果 s 应该排在前面,就返回1,如果两者相当,返回 0。
一个类表现得像一个list,要获取有多少个元素,就得用 len() 函数。
函数工作正常,类必须提供一个特殊方法len(),它返回元素的个数。
一个 Students 类,把名字传进去:
一个Rational类来表示:
函数正常工作,只需要实现特殊方法float()。
score(1000) 就会报错。
方法来封装对一个属性的访问在许多面向对象编程的语言中都很常见。
score() 和 s.set_score() 没有直接写 s.score 来得直接。
方法?----有。
支持高阶函数,在函数式编程中我们介绍了装饰器函数,可以用装饰器函数把 get/set 方法“装饰”成属性调用:
一个score(self)是get方法,用@property装饰,第二个score(self,score)是set方法,用@score.setter装饰,@score.setter是前一个@property装饰后的副产品。
属性一样设置score了:
添加属性。
添加的属性,例如,Student类只允许添加 name、gender和score 这3个属性,就可以利用Python的一个特殊的slots来实现。
一个类允许的属性列表:
属性,如果不需要添加任意动态的属性,使用slots也能节省内存。
函数其实是一个对象:
调用:
一个父类继承外,Python允许从多个父类继承,称为多重继承。
功能。多重继承通过 super()调用init()方法时,A 虽然被继承了两次,但init()只调用一次:
功能使用。
方法
默认的比较函数 cmp 排序,但是,如果对一组 Student 类的实例排序时,就必须提供我们自己的特殊方法 cmp():
方法,cmp用实例自身self和传入的实例 s 进行比较,如果 self 应该排在前面,就返回 -1,如果 s 应该排在前面,就返回1,如果两者相当,返回 0。
一个类表现得像一个list,要获取有多少个元素,就得用 len() 函数。
函数工作正常,类必须提供一个特殊方法len(),它返回元素的个数。
一个 Students 类,把名字传进去:
一个Rational类来表示:
函数正常工作,只需要实现特殊方法float()。
score(1000) 就会报错。
方法来封装对一个属性的访问在许多面向对象编程的语言中都很常见。
score() 和 s.set_score() 没有直接写 s.score 来得直接。
方法?----有。
支持高阶函数,在函数式编程中我们介绍了装饰器函数,可以用装饰器函数把 get/set 方法“装饰”成属性调用:
一个score(self)是get方法,用@property装饰,第二个score(self,score)是set方法,用@score.setter装饰,@score.setter是前一个@property装饰后的副产品。
属性一样设置score了:
添加属性。
添加的属性,例如,Student类只允许添加 name、gender和score 这3个属性,就可以利用Python的一个特殊的slots来实现。
一个类允许的属性列表:
属性,如果不需要添加任意动态的属性,使用slots也能节省内存。
函数其实是一个对象:
调用:
总结
以上是编程之家为你收集整理的Python进阶教程!这还学不会?那就找我!手把手带你!比教科书还详细!全部内容,希望文章能够帮你解决Python进阶教程!这还学不会?那就找我!手把手带你!比教科书还详细!所遇到的程序开发问题。
如果您也喜欢它,动动您的小指点个赞吧