博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
进阶第二课 Python内置函数(补)及自定义函数
阅读量:6258 次
发布时间:2019-06-22

本文共 7048 字,大约阅读时间需要 23 分钟。

内置函数(补)

1、float()

上一课中,我们可以使浮点数变为整数;相反的也可以把整数变为浮点数。看示例:

>>> a=10>>> b=float(10)>>> b10.0

2、max()

在一系列数中取最大的一个。看示例:

>>> max(1,2,3,4,5)5

3、min()

在一系列数中取最小的一个。看示例:

>>> min(1,2,3,4,5)1

4、help()

查看说明。看示例:

>>> help(int)

大家自己试试看int的说明。

5、迭代器

上一课我们介绍了iter()这个内置函数。这里再详细介绍一下。

5.1 可以直接作用于for循环的对象统称为可迭代对象(Iterable)。

5.2 可以被next()函数调用并不断返回下一个值的对象称为迭代器(Iterator)。

5.3 所有的Iterable均可以通过内置函数iter()来转变为Iterator。

5.4 对迭代器来讲,有一个__next()就够了。在你使用for 和 in 语句时,程序就会自动调用即将被处理的对象的迭代器对象,然后使用它的next__()方法,直到监测到一个StopIteration异常。

>>> a=[1,2,3]>>> b=iter(a)>>> next(b)1>>> next(b)2>>> next(b)3>>> next(b)Traceback (most recent call last):  File "
", line 1, in
next(b)StopIteration

a是一个列表,也就是可迭代对象。b是一个迭代器。

6、yield()

 6.1 使用了yield的函数叫生成器,即生成器函数。还可以用生成器表达式来创建生成器:

>>> a=[x**2 for x in range(10)]>>> a[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]>>> b=(x**2 for x in range(10))>>> b
at 0x000001FDA3A7D780>

分析一下:a是一个列表,a所有的值都储存在计算机的内存中;b是一个生成器。

要想打印生成器中的内容,有2中方法:

1)next()

>>> g.next()0>>> g.next()1>>> g.next()4>>> g.next()9>>> g.next()16>>> g.next()25>>> g.next()36>>> g.next()49>>> g.next()64>>> g.next()81>>> g.next()Traceback (most recent call last):  File "
", line 1, in
StopIteration

当b中的值调出完毕后,再执行next(),系统会报错。

2)for循环

>>> b=(x**2 for x in range(10))>>> for i in b:        print(i,end=' ')    0 1 4 9 16 25 36 49 64 81

  >>> for i in b:

          print(i,end=' ')

  

  >>>

这里可以看到b作为一个生成器,完成一个循环后就无法再次使用。

6.2 生成器函数

生成器也是一个函数,返回一个迭代器。简单想生成器也是一个迭代器。

在调用生成器时,一旦遇到 yield 函数会暂停并保存当前所有的运行信息(也就是函数内所有变量的状态会被保留,同时函数代码执行到的位置会被保留,感觉就像函数被暂停了一样),并返回 yield 的值,在下一次执行 next() 方法时从当前位置继续运行。

看示例:

>>> def pingfang_2(a):    b=1    while b<=a:        yield b**2        b=b+1        >>> for i in pingfang_2(5):        print(i)    1491625

分析一下:

1)函数pingfang_2中使用yield来返回一个值而非return返回值,所以这个函数是一个生成器,调用这个函数就会返回一个迭代器(即pingfang_2(5))。

2)生成器的好处是延迟计算,一次返回一个结果。也就是说,它不会一次生成所有的结果,这对于大数据量处理,将会非常有用。举个栗子-_-!!

sum(i for i in range(10000000000))

虽然range的范围很大,到10的10次方。但是由于使用的是(),所以i实在一个生成器中循环,每次生成器只返回一个数字:0,1,2,3...占用内存极小。

反例也有一个:

sum([i for i in range(10000000000)])

执行之前请先检查是否为64位操作系统,内容是否为16GB以上,否则你还没等看明白怎么回事你的电脑就死机啦。。。

因为使用的是[],意味着首先生成一个列表,从0到10的10次幂-1。列表越大占用内存越多,会显著降低电脑的运行速度甚至死机。每次也是取一个数。

 另外,我碰到这样一个问题:

电脑配置:AMD1600,win10,使用节能模式,显示CPU主频1.32GHz,内存16GB@3000MHz。

此时我执行下列代码:

>>> def time1():        import time        a=time.time()        sum([i for i in range(10000000)])        b=time.time()        return b-a>>> time1()1.9722506999969482>>> def time2():        import time        a=time.time()        sum(i for i in range(10000000))        b=time.time()        return b-a>>> time2()2.1406807899475098

生成器虽说节省内存,但是速度竟然比列表慢!!!

然后我把电源模式改为了“高性能”,再次执行上述2个函数:

>>> time1()0.8594393730163574>>> time2()0.8438072204589844

这一次结果相反!!!生成器即节省内存,又节省时间。

同样是高性能下,把range增加10倍,看结果:

>>> def time3():        import time        a=time.time()        sum([i for i in range(100000000)])        b=time.time()        return b-a>>> def time4():        import time        a=time.time()        sum(i for i in range(100000000))        b=time.time()        return b-a>>> time3()8.884530067443848>>> time4()8.421962976455688

时间差距不明显。内存消耗差距大。

内置函数先讲这些,今后碰到没讲的,随时补充。下面介绍下自定义函数。

自定义函数

介绍了这么多内置的函数,那我们可以自己编写函数吗?可以的,称之为自定义函数。无论是内置的函数,还是我们自定义的函数,都是可以重复使用的。

1、函数的格式:

>>> def add_1(a,b):        return(a+b)>>> add_1(10,15)25

 看看格式:

1.1 def开头 ,空格后是自定义函数的函数名,这个函数名的命名不要与系统内置的函数名重复,且命名与变量一样开头字符可以是下划线或者英语字母,不能使数字开头。

1.2 函数名后面是括号,里面是参数,可以没有参数,看示例:

>>> def _print():        print('I wanna learn Python.')    >>> _print()I wanna learn Python.

1.3 自定义函数内部,依然可以添加说明,与之前的用法一致;

1.4 注意缩进。

1.5 看下取值逻辑:

>>> def mianji(chang,kuan):        s=chang*kuan      print('长:',chang)      print('宽:',kuan)      print("面积是:")      return s>>> mianji(20,50)长: 20宽: 50面积是:1000

函数mianji中,定义了2个参数:chang和kuan。引用函数时,也提供了这2个参数对应的值。可以看到函数参数和调用时提供的参数,是有对应顺序的:chang对应的是20,kuan对应的是50。

1.6 因为函数mianji中定义了2个参数,调用时如果只传入一个,会怎么样呢?看示例:

>>> mianji(20)Traceback (most recent call last):  File "
", line 1, in
mianji(20)TypeError: mianji() missing 1 required positional argument: 'kuan'

会报错!提示缺少一个参数值,这个参数值对应的参数是kuan。

1.7 再一个问题:调用自定义函数时,是否可以改变参数的顺序呢?看示例。

>>> mianji(kuan=50,chang=20)长: 20宽: 50面积是:1000

答案是可以的。无非就是在调用自定义函数时,在括号中把函数的参数和值一并写入。

1.8 默认参数

>>> def person(name,age,salary=10000):      print(name)      print(age)      print(salary)    >>> person('zhaoyun',23)zhaoyun2310000>>> person('zhaoyun',23,5000)zhaoyun235000>>> person(age=23,name='zhaoyun',8000)SyntaxError: positional argument follows keyword argument>>> person(age=23,name='zhaoyun',salary=8000)zhaoyun238000

在自定义函数person中有3个参数,其中salary给出了默认值10000。调用时,如果不提供salary这个参数的值,就会按默认值打印出来;如果给出新的值,就会打印新的值。

再就是如果通过参数名给出对应值,那么所有参数都要标出,否则会报错。

1.9 如果想自定义一个函数,且该函数的参数个数不固定,要如何处理呢?看示例:

>>> def buguding1(*args):      print(args)    >>> buguding1(1,2,3,45,5)(1, 2, 3, 45, 5)>>> buguding1([1,2,4,43,5,7])([1, 2, 4, 43, 5, 7],)

当参数个数不固定,可以使用*args作为参数。当然‘args’并不是一个固定的名称,说必须使用*args作为不固定参数,使用*a或者*_12a也可以。不过既然多数人都使用*args,那么你也这么用。

上面调用时,我们传入了元祖和列表,都可以正常打印。

还可以这么用:

>>> def buguding_2(a,*args):      print(a)      print(args)    >>> buguding_2(1,2,3,4,5)1(2, 3, 4, 5)

参数有2部分,注意不是2个。第一部分是一个参数a,第二部分是一个不固定个数的参数*args。调用时,1赋值给了a,其余的2,3,4,5赋值给了args。

还可以这样使用:

>>> def buguding_2(a,*args,b):      print(a)      print(args)      print(b)    >>> buguding_2(1,2,3,4,5)Traceback (most recent call last):  File "
", line 1, in
buguding_2(1,2,3,4,5)TypeError: buguding_2() missing 1 required keyword-only argument: 'b'>>> buguding_2(1,2,3,4,b=5)1(2, 3, 4)5

有3部分参数,a、*args和b。调用时如果不指定b的值就会报错,以为*args包含了除第一个参数外所有值,b就没有传入值。指定b的值之后,就没问题了。

1.10 如果传入的参数是字典,就需要使用另一种方式:

>>> def buguding_3(**kwargs):      print(kwargs)    >>> buguding_3(name='zhaoyun',age=23,salary=10000){
'name': 'zhaoyun', 'age': 23, 'salary': 10000}

 如果传入值是字典类型且不固定长度,就可以使用**kwargs作为函数的参数。当然**a也可以。道理同上。

1.11 *args和**kwargs可以混用。看示例:

>>> def buguding_4(*args,**kwargs):      print(args)      print(kwargs)

这样一来,这个自定义函数就能打印传入的元祖、列表和字典。看示例:

>>> buguding_4(1,2,3,5,6)(1, 2, 3, 5, 6){}

调用时只传入了一个元祖,并未传入字典,此时程序默认传入的是一个空字典。反之亦然。看示例:

>>> buguding_4(name='zhaoyun',age=23,height=200)(){
'name': 'zhaoyun', 'age': 23, 'height': 200}

调用时如果只传入一个字典,那么程序默认你也传入了一个元祖,不过是空元组罢了。

>>> buguding_4(1,2,3,5,6,name='zhaoyun',age=23,height=200)(1, 2, 3, 5, 6){
'name': 'zhaoyun', 'age': 23, 'height': 200}

同时传入元祖和字典的结果。

>>> buguding_4(name='zhaoyun',age=23,height=200,1,2,3,5,6,)SyntaxError: positional argument follows keyword argument

调用时如果颠倒参数顺序,结果就是报错。

1.12 不用定义的函数,称之为‘匿名函数’,格式也有所不同。看示例:

>>> a=lambda x,y:x+y>>> a(10,100)110

使用lambda定义一个函数,lambda后面是变量,用逗号隔开,然后是冒号,最后是变量的算法也就是返回值。调用时输入参数即可。

 1.13 变量的作用域。

所谓变量的作用域,就是指变量的有效范围。先看示例:

>>> a=10>>> b=2>>> c=a**b>>> c100

上面这段程序中,c的值由a和b计算得来,说明在计算c的值过程中,a和b都起了作用。那么在这一过程,都是a和b的作用域。再看另一个例子:

>>> def pingfang(a):      return a**2>>> pingfang(10)100>>> aTraceback (most recent call last):  File "
", line 1, in
aNameError: name 'a' is not defined

这段代码中,函数pingfang中有一个参数a,a也是一个变量。a这个变量的作用域就是函数pingfang内,一旦出了这个函数,a就不存在了。

转载于:https://www.cnblogs.com/tuobeiwoniu/p/8665472.html

你可能感兴趣的文章
Spring Boot中使用MyBatis注解配置详解
查看>>
linux下文件的一些文件颜色的含义
查看>>
跨域iframe高度自适应(兼容IE/FF/OP/Chrome)
查看>>
如何花更少的时间学习更多的知识
查看>>
学习鸟哥的Linux私房菜笔记(8)——文件查找与文件管理2
查看>>
升级fedora 18到fedora 19
查看>>
【代码小记】无
查看>>
BarTender 2016表单中的“秤显示”控件
查看>>
11月20日学习内容整理:jquery插件
查看>>
Redis客户端集群
查看>>
javascript基础篇:函数
查看>>
SVN与TortoiseSVN实战:补丁详解
查看>>
java一些面试题
查看>>
干货型up主
查看>>
获取页面中所有dropdownlist类型控件
查看>>
读《淘宝数据魔方技术架构解析》有感
查看>>
[转载]如何破解Excel VBA密码
查看>>
【BZOJ】2563: 阿狸和桃子的游戏
查看>>
redis 中文字符显示
查看>>
国内外MD5在线解密网站
查看>>