六.python函数基础

 

1.什么是函数

  • 定义:函数是对程序逻辑进行结构化或过程化的一种编程方法。
  • 特点:

  1.能将整块代码巧妙地隔离成易于管理的小块

  2.很多重复性的代码放到函数中能节省大量的空间

  • 函数的定义方法
 1 #!/usr/bin/env python
 2 # -*- coding: utf-8 -*-
 3 # @Author  : All is well
 4 # @Software: PyCharm
 5 
 6 
 7 def pingfang(x):
 8     "定义一个计算平方函数"
 9     result = x * x
10     return result
11 
12 
13 # def :定义函数的关键字
14 # pingfang:函数名
15 # ():内可定义形参
16 # "":文档描述(非必要,但是强烈建议为你的函数添加描述信息)
17 # result = x * x :指代码块或程序处理逻辑
18 # return:定义返回值
19 
20 # 调用运行:可以带参数也可以不带(指定默认参数可以不带,后面会有介绍)
21 # 函数名()
22 
23 #这里计算3的平方
24 print(pingfang(3))
25 # 结果:
26 9
函数定义的方法

 

2.为什么要使用函数

身边的例子

 一般公司都会监控服务器的硬件信息,是否有异常,就用平常监控的,cpu,内存,硬盘举例。

如果在我们没有函数的时候,我们会像以下这样写脚本。

 1 #!/usr/bin/env python
 2 # -*- coding: utf-8 -*-
 3 while True:
 4 if cpu利用率 > 80 %:
 5     # 发送邮件提醒
 6     连接邮箱服务器
 7     发送邮件
 8     关闭连接
 9 
10 if 硬盘使用空间 > 80 %:
11     # 发送邮件提醒
12     连接邮箱服务器
13     发送邮件
14     关闭连接
15 
16 if 内存占用 > 80 %:
17     # 发送邮件提醒
18     连接邮箱服务器
19     发送邮件
20     关闭连接
普通监控脚本举例

这样写是没有问题,但是有些时候需求变了,部门总监也要收到监控

 1 #!/usr/bin/env python
 2 # -*- coding: utf-8 -*-
 3 
 4 while True:
 5 if cpu利用率 > 80 %:
 6     # 发送邮件提醒
 7     连接邮箱服务器
 8     发送邮件
 9     发送邮件给总监
10     关闭连接
11 
12 if 硬盘使用空间 > 80 %:
13     # 发送邮件提醒
14     连接邮箱服务器
15     发送邮件
16     发送邮件给总监
17     关闭连接
18 
19 if 内存占用 > 80 %:
20     # 发送邮件提醒
21     连接邮箱服务器
22     发送邮件
23     发送邮件给总监
24     关闭连接
给领导发送报警信息

 但是某一天,需求又增加了,我们不同项目的报警要给不同的人看,这个时候我们还得继续在每个判断里面加各种人员

目前就有两个问题:

1.代码纯复制粘贴,改判断,不易于维护

2.很多重复性的代码,可读性较低

3.需求一变,我们不好应对,甚至会改整个脚本。

这几点恰好是函数的特点。这时候我们就用函数来试一试。

因为代码有重复性,我们可以提取重复的部分,就比如发送邮件这部分。

 1 #!/usr/bin/env python
 2 # -*- coding: utf-8 -*-
 3 
 4 def 发送邮件(内容)
 5     #发送邮件提醒
 6     连接邮箱服务器
 7     发送邮件
 8     发送邮件给领导   #以后发送邮件报警,只在这里添加即可
 9     关闭连接
10      
11 while True:
12      
13     if cpu利用率 > 80%:
14         发送邮件('CPU报警')
15      
16     if 硬盘使用空间 > 80%:
17         发送邮件('硬盘报警')
18      
19     if 内存占用 > 80%:
20         发送邮件('内存报警')
利用函数

用了函数,这里的代码大概节省了一半的空间,而且可读性也非常高。
这个例子,总结函数的好处(这就是我们为什么要使用函数)

1.代码重用

2.保持一致性,可扩展,易维护

3.函数的参数

  • 形参介绍:

  形参变量只有在被调用时才分配内存单元,在调用结束时,即刻释放所分配的内存单元。因此,形参只在函数内部有效。函数调用结束返回主调用函数后则不能再使用该形参变量

  • 实参介绍:

  实参可以是常量、变量、表达式、函数等,无论实参是何种类型的量,在进行函数调用时,它们都必须有确定的值,以便把这些值传送给形参。因此应预先用赋值,输入等办法使参数获得确定值

 3.1参数的分类

3.1.1 位置参数

  • 调用时输入参数的值,且与函数声明时的参数名称位置保持一致。
1 # 函数定义
2 def foo(x, y):
3     print 'x is %s' % x
4     print 'y is %s' % y
5 
6 
7 # 位置参数调用(1为x,2为y,位置一一对应)
8 foo(1, 2)
位置参数举例

 

3.1.2 默认参数

  • 在函数声明时,指定形参的默认值,调用时可不传入参数(不传入会使用默认值)。 
1 # 函数定义
2 def foo(x, y=2):       #y=2为默认参数定义方式
3     print 'x is %s' % x
4     print 'y is %s' % y
5 
6 #默认参数调用(这里不指定y,默认y=2)
7 foo(1)
默认参数举例

3.1.3 关键字参数

  • 调用时指定参数的名称,且与函数声明时的参数名称一致。使用关键字参数允许函数调用时参数的顺序与声明时不一致,仅根据参数的指定进行赋值。
1 # 函数定义
2 def foo(x, y):
3     print 'x is %s' % x
4     print 'y is %s' % y
5 
6 # 关键字调用(顺序无所谓,仅仅和参数的赋值有关)
7 foo(y = 1, x = 2)
关键字参数举例

 

3.1.4 可变参数(非关键字

  • 可变参数就是传入的参数个数是可变的,可以是1个、2个到任意个,还可以是0个,这些可变参数在函数调用时自动组装为一个tuple
 1 #比如需求是我们要打印所有的参数,我们可以这样定义
 2 >>> def testprint(args):
 3 ...     for i in args:
 4 ...         print(i)
 5 ... 
 6 >>> 
 7 >>> 
 8 #调用的时候要组成一个tuple或list,而且不能为空,否则会报错
 9 >>> testprint([1,2,3,4])
10 1
11 2
12 3
13 4
14 >>> testprint((1,2,3,4))
15 1
16 2
17 3
18 4
19 #错误调用
20 >>> testprint() 
21 Traceback (most recent call last):
22   File "<stdin>", line 1, in <module>
23 TypeError: testprint() missing 1 required positional argument: 'args'
24 >>> 
25 
26 #以下用可变参数实现(可以变长变短,输入几个参数都会一一对应向后排列)
27 
28 >>> def testprint(*args):
29 ...     for i in args:
30 ...         print(i)
31 ... 
32 >>> testprint(1,2,3) #可以直接调用,
33 1
34 2
35 3
36 >>> testprint('test1','test2','test3')
37 test1
38 test2
39 test3
40 >>> testprint()        #调用值也可以为空                    
41 >>> 
42 
43 #如果有一个list或者tuple也要传入到可变参数,怎么办呢,我们一般会这样实现
44 >>> a = [1,2,3]
45 >>> testprint(a[0],a[1],a[2])
46 1
47 2
48 3
49 >>> 
50 
51 #但是学过可变参数之后,我们可以这么做
52 >>> a = [1,2,3]
53 >>> testprint(*a)   #*a 会把列表内的所有元素作为可变参数传入(重点*****)
54 1
55 2
56 3
57 >>> 
可变参数举例

 

3.1.5 可变参数(关键字

  • 关键字参数也是可变参数的一种,它允许你传入0个或任意个含参数名的参数,这些关键字参数在函数内部自动组装为一个dict

  上面说过关键字参数,但是不可变,形参定义几个关键字,调用就得有对应的关键字,比如下面获取用户信息的例子

1 >>> def person(name, age):
2 ...     print 'name is %s' % name
3 ...     print 'age is %s' % age
4 ... 
5 >>> person(name = 'All is well', age = 23)   
6 name is All is well
7 age is 23
8 >>> 

  以上例子只能输入姓名和年龄,如果有其他信息还得添加参数,每次都需要修改参数和调用,很麻烦,这个时候我们就用到了关键字的可变参数。如下示例

 1 >>> def person(name, age,**kwargs):
 2 ...     print 'name is %s' % name
 3 ...     print 'age is %s' % age
 4 ...     print 'other is %s' %kwargs
 5 ... 
 6 >>> person(name='all is well',age='23',city='beijing',Gender='M')
 7 name is all is well
 8 age is 23
 9 other is {'city': 'beijing', 'Gender': 'M'}
10 >>> 
11 #因为关键字参数可以为0个关键字,我们不需要的时候也可以不输入
12 >>> person(name='all is well',age='23')                          
13 name is all is well
14 age is 23
15 other is {}
16 >>> 
可变关键字参数示例

 

3.1.6 可变参数(命名关键字

  • 可变命名关键字其实就是可变关键字的一种,唯一的区别就是可变命名关键字可以定制都可以命哪些名字,而不是随意变长。(目前测试只在python3中可以使用******

  以下还按照用户信息来举例

1 >>> def person(name, age,**kwargs):
2 ...     print 'name is %s' % name
3 ...     print 'age is %s' % age
4 ...     print 'other is %s' %kwargs
5 ... 
6 
7 >>> person(name='all is well',age='23',city='beijing',Gender='M')

  可变关键字参数这里的other可以无限的增加,有时候我们要将other里定义好一些参数,其他不存在的条件不允许添加,比如我们只能输入城市和性别,其他的不允许输入,我们可以这样做。

 1 >>> def person(name, age,*,city,Gender): #这里定义只能定义city和Gender参数
 2 ...     print('name is %s' %name)
 3 ...     print('age is %s' %age)
 4 ...     print('other is %s,%s' %(city,Gender))
 5 ... 
 6 
 7 >>> person(name='all is well',age='23',city='beijing',Gender='M')
 8 name is all is well
 9 age is 23
10 other is beijing,M
11 
12 #错误示例,这里输入没有定制的work参数会报错
13 >>> person(name='all is well',age='23',city='beijing',Gender='M',work='IT')
14 Traceback (most recent call last):
15   File "<stdin>", line 1, in <module>
16 TypeError: person() got an unexpected keyword argument 'work'
17 >>> 
可变命名关键字参数示例

 

4.局部变量和全局变量

  • 局部变量:
    在子程序中定义的变量称为局部变量,它们与程序外具有相同名称的其他变量没有任何关系。
  • 全局变量:
    在整个程序外定义的变量称为全局变量,如果你想要为一个定义在程序外的变量赋值,可以使用global语句完成这个功能,没有global语句,是不可能为定义在函数外的变量赋值的。
  • 注意:当全局变量与局部变量重名的时候,在程序的内部定义局部变量的局部变量起作用,在其他地方,全局变量起作用。

  示例如下:

 1 #当没有局部变量的时候,程序会引用全局变量
 2 name='All is well'
 3 
 4 def my_name():
 5     print('my name is',name)
 6 
 7 my_name()
 8 
 9 #结果:
10 my name is All is well
11 ####################################
12 #当程序内部定义好局部变量的时候,程序会优先引用局部变量
13 name='All is well'
14 
15 def my_name():
16     name='zhangsan'
17     print('local variable is',name)
18 
19 my_name()
20 print('global variable is',name)
21 #结果:
22 >>> my_name()
23 local variable is zhangsan
24 >>> print('global variable is',name)
25 global variable is All is well
26 ####################################
27 #想要引用或者为程序外的全局变量赋值的时候,这时候用global
28 name='All is well'
29 def my_name():
30     global name               #引用全局变量
31     name='zhangsan'       #修改全局变量
32     print('Changed global to',name)
33 
34 print('global variable is',name)
35 my_name()
36 print('global variable is',name)
37 #结果:
38 >>> print('global variable is',name)
39 global variable is All is well
40 >>> my_name()
41 Changed global to zhangsan
42 >>> print('global variable is',name)
43 global variable is zhangsan
局部变量和全局变量示例

 

5.递归函数

  • 定义:如果一个函数在内部调用自身本身,这个函数就是递归函数。
  • 递归的特点:大大缩短程序的代码,可以用较短的代码解决一些复杂的问题
  • 递归算法的基本思想是:把规模大的、较难解决的问题变成规模较小的、易解决的同一问题。规模较小的问题又变成规模更小的问题,并且小到一定程度可以直接得出它的解,从而得到原来问题的解。
  • 一个问题要采用递归方法来解决时,必须符合以下三个条件:
  1. 解决问题时,可以把一个问题转化为一个新的问题,而这个新的问题的解决方法仍与原问题的解法相同,只是所处理的对象有所不同,这些被处理的对象之间是有规律的递增或递减。
  2. 可以通过转化过程使问题得到解决。
  3. 必定要有一个明确的结束递归的条件,否则递归将会无止境地进行下去,直到耗尽系统资源。也就是说必须要写终止递归的条件。
  • 递归与循环做对比

  递归算法

  • 优点:代码简洁、清晰,并且容易验证正确性。
  • 缺点:它的运行需要较多次数的函数调用,如果调用层数比较深,每次都要创建新的变量,需要增加额外的堆栈处理,会对执行效率有一定影响,占用过多的内存资源。

  循环算法: 

  • 优点:速度快,结构简单。
  • 缺点:并不能解决所有的问题。有的问题适合使用递归而不是循环。如果使用循环并不困难的话,最好使用循环。

  注:不要认为递归和循环是一个道理,递归与循环是两种不同的解决问题的典型思路。

  一个阶乘的例子:

    计算阶乘n! = 1 x 2 x 3 x ... x n,用函数fact(n)表示,可以看出:

    fact(n) = n! = 1 x 2 x 3 x ... x (n-1) x n = (n-1)! x n = fact(n-1) x n

    所以,fact(n)可以表示为n x fact(n-1),只有n=1时需要特殊处理。

    于是,fact(n)用递归的方式写出来就是: 

1 #!/usr/bin/env python
2 #--*--conding:utf-8--*--
3 
4 def fact(n):
5     if n==1:
6         return 1
7     return n * fact(n - 1)

执行如下:

 1 >>> fact(1)
 2 1
 3 >>> fact(2)
 4 2
 5 >>> fact(3)
 6 6
 7 >>> fact(4)
 8 24
 9 >>> fact(5)
10 120
11 >>> 

计算过程如下:

 1 ===> fact(5)
 2 ===> 5 * fact(4)
 3 ===> 5 * (4 * fact(3))
 4 ===> 5 * (4 * (3 * fact(2)))
 5 ===> 5 * (4 * (3 * (2 * fact(1))))
 6 ===> 5 * (4 * (3 * (2 * 1)))
 7 ===> 5 * (4 * (3 * 2))
 8 ===> 5 * (4 * 6)
 9 ===> 5 * 24
10 ===> 120

递归的缺点:由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出。如下:

>>> fact(999)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 4, in fact
  ...
  File "<stdin>", line 4, in fact
RuntimeError: maximum recursion depth exceeded in comparison

栈溢出的优化方法,利用尾递归的方法,尾递归是指,在函数返回的时候,调用自身本身,并且,return语句不能包含表达式。这样,编译器或者解释器就可以把尾递归做优化,使递归本身无论调用多少次,都只占用一个栈帧,不会出现栈溢出的情况。

 

#!/usr/bin/env python
#--*--coding:utf-8--*--
def fact(n):
    return fact_iter(n, 1)

def fact_iter(num, product):
    if num == 1:
        return product
    return fact_iter(num - 1, num * product)

可以看到,return fact_iter(num - 1, num * product)仅返回递归函数本身,num - 1num * product在函数调用前就会被计算,不影响函数调用。

fact(5)对应的fact_iter(5, 1)的调用如下:

1 ===> fact_iter(5, 1)
2 ===> fact_iter(4, 5)
3 ===> fact_iter(3, 20)
4 ===> fact_iter(2, 60)
5 ===> fact_iter(1, 120)
6 ===> 120

尾递归调用时,如果做了优化,栈不会增长,因此,无论多少次调用也不会导致栈溢出。

遗憾的是,大多数编程语言没有针对尾递归做优化,Python解释器也没有做优化,所以,即使把上面的fact(n)函数改成尾递归方式,也会导致栈溢出。

注:Python标准的解释器没有针对尾递归做优化,任何递归函数都存在栈溢出的问题。

6.匿名函数

  • 定义:顾名思义,没有函数名的函数称为匿名函数
  • 基本语法:lambda [arg1[,arg2,...argN]]: expression
  • 匿名函数的好处:因为函数没有名字,不必担心函数名冲突。此外,匿名函数也是一个函数对象,也可以把匿名函数赋值给一个变量,再利用变量来调用该函数
 1 #普通函数
 2 >>> def run(x):
 3 ...     return x * x
 4 ... 
 5 >>> run(10)
 6 100
 7 >>> 
 8 
 9 #匿名函数可以这么定义
10 
11 >>> run = lambda x: x * x   
12 >>> 
13 >>> run(10)
14 100
15 >>> 
基本示例


注:匿名函数常和一些内置函数配合使用,一是定义起来方便,二是代码简洁,不需要从新写个函数。

7.高阶函数

  • 高阶函数必须满足以下两个需求

  1. 函数的传入参数是一个函数名

  2. 函数的返回值是一个函数名

 1 #函数接收的参数是一个函数名
 2 
 3 def foo(n):
 4     print(n)
 5 
 6 def bar(name):
 7     print("my name is %s" %name)
 8 
 9 foo(bar('All is well'))
10 
11 #返回值中包含函数
12 
13 def bar():
14     print("from bar")
15 def foo():
16     print("from foo")
17     return bar
18 
19 res=foo()
20 res()
高阶函数示例

 

8.内置函数

8.1 python3.6.2版本的内置函数

  Built-in Functions  
abs() dict() help() min() setattr()
all() dir() hex() next() slice()
any() divmod() id() object() sorted()
ascii() enumerate() input() oct() staticmethod()
bin() eval() int() open() str()
bool() exec() isinstance() ord() sum()
bytearray() filter() issubclass() pow() super()
bytes() float() iter() print() tuple()
callable() format() len() property() type()
chr() frozenset() list() range() vars()
classmethod() getattr() locals() repr() zip()
compile() globals() map() reversed() __import__()
complex() hasattr() max() round()  
delattr() hash() memoryview() set()  

8.2 内置函数进行分类

8.2.1 数学运算类
abs(x) 求绝对值 1、参数可以是整型,也可以是复数 2、若参数是负数,则返回负数的模
complex([real[, imag]]) 创建一个复数
divmod(a, b) 分别取商和余数 注意:整型、浮点型都可以
float([x]) 将一个字符串或数转换为浮点数。如果无参数将返回0.0
int([x[, base]])  将一个字符转换为int类型,base表示进制
long([x[, base]])  将一个字符转换为long类型
pow(x, y[, z])  返回x的y次幂
range([start], stop[, step])  产生一个序列,默认从0开始
round(x[, n])  四舍五入
sum(iterable[, start])  对集合求和
oct(x) 将一个数字转化为8进制
hex(x) 将整数x转换为16进制字符串
chr(i) 返回整数i对应的ASCII字符
bin(x)

将整数x转换为二进制字符串

bool([x]) 将x转换为Boolean类型
8.2.2 集合类操作
basestring() str和unicode的超类 不能直接调用,可以用作isinstance判断
format(value [, format_spec]) 格式化输出字符串 格式化的参数顺序从0开始,如“I am {0},I like {1}”
unichr(i) 返回给定int类型的unicode
enumerate(sequence [, start = 0]) 返回一个可枚举的对象,该对象的next()方法将返回一个tuple
iter(o[, sentinel]) 生成一个对象的迭代器,第二个参数表示分隔符
max(iterable[, args...][key])  返回集合中的最大值
min(iterable[, args...][key]) 返回集合中的最小值
dict([arg]) 创建数据字典
list([iterable])  将一个集合类转换为另外一个集合类
set() set对象实例化
frozenset([iterable]) 产生一个不可变的set
str([object])  转换为string类型
sorted(iterable[, cmp[, key[, reverse]]])  队集合排序
tuple([iterable])  生成一个tuple类型
xrange([start], stop[, step])  xrange()函数与range()类似,但xrnage()并不创建列表,而是返回一个xrange对象,它的行为与列表相似,但是只在需要时才计算列表值,当列表很大时,这个特性能为我们节省内存
8.2.3 逻辑判断操作
all(iterable) 1、集合中的元素都为真的时候为真 2、特别的,若为空串返回为True
any(iterable) 1、集合中的元素有一个为真的时候为真 2、特别的,若为空串返回为False
cmp(x, y) 如果x < y ,返回负数;x == y, 返回0;x > y,返回正数
8.2.4 反射操作
callable(object) 检查对象object是否可调用 1、类是可以被调用的 2、实例是不可以被调用的,除非类中声明了__call__方法
classmethod() 1、注解,用来说明这个方式是个类方法 2、类方法即可被类调用,也可以被实例调用 3、类方法类似于Java中的static方法 4、类方法中不需要有self参数
compile(source, filename, mode[, flags[, dont_inherit]]) 将source编译为代码或者AST对象。代码对象能够通过exec语句来执行或者eval()进行求值。 1、参数source:字符串或者AST(Abstract Syntax Trees)对象。 2、参数 filename:代码文件名称,如果不是从文件读取代码则传递一些可辨认的值。 3、参数model:指定编译代码的种类。可以指定为 ‘exec’,’eval’,’single’。 4、参数flag和dont_inherit:这两个参数暂不介绍
dir([object]) 1、不带参数时,返回当前范围内的变量、方法和定义的类型列表; 2、带参数时,返回参数的属性、方法列表。 3、如果参数包含方法__dir__(),该方法将被调用。当参数为实例时。 4、如果参数不包含__dir__(),该方法将最大限度地收集参数信息
delattr(object, name) 删除object对象名为name的属性
eval(expression [, globals [, locals]]) 计算表达式expression的值
execfile(filename [, globals [, locals]]) 用法类似exec(),不同的是execfile的参数filename为文件名,而exec的参数为字符串。
filter(function, iterable) 构造一个序列,等价于[ item for item in iterable if function(item)] 1、参数function:返回值为True或False的函数,可以为None 2、参数iterable:序列或可迭代对象
getattr(object, name [, defalut]) 获取一个类的属性
globals() 返回一个描述当前全局符号表的字典
hasattr(object, name) 判断对象object是否包含名为name的特性
hash(object) 如果对象object为哈希表类型,返回对象object的哈希值
id(object) 返回对象的唯一标识
isinstance(object, classinfo) 判断object是否是class的实例
issubclass(class, classinfo) 判断是否是子类
len(s)  返回集合长度
locals()  返回当前的变量列表
map(function, iterable, ...)  遍历每个元素,执行function操作
memoryview(obj)  返回一个内存镜像类型的对象
next(iterator[, default])  类似于iterator.next()
object()  基类
property([fget[, fset[, fdel[, doc]]]])  属性访问的包装类,设置后可以通过c.x=value等来访问setter和getter
reduce(function, iterable[, initializer])  合并操作,从第一个开始是前两个参数,然后是前两个的结果与第三个合并进行处理,以此类推
reload(module)  重新加载模块
setattr(object, name, value) 设置属性值
repr(object)  将一个对象变幻为可打印的格式
slice()  
staticmethod 声明静态方法,是个注解
super(type[, object-or-type])  引用父类
type(object) 返回该object的类型
vars([object])  返回对象的变量,若无参数与dict()方法类似
bytearray([source [, encoding [, errors]]]) 返回一个byte数组 1、如果source为整数,则返回一个长度为source的初始化数组; 2、如果source为字符串,则按照指定的encoding将字符串转换为字节序列; 3、如果source为可迭代类型,则元素必须为[0 ,255]中的整数; 4、如果source为与buffer接口一致的对象,则此对象也可以被用于初始化bytearray.
zip([iterable, ...])  实在是没有看懂,只是看到了矩阵的变幻方面

 

8.2.5 IO操作
file(filename [, mode [, bufsize]]) file类型的构造函数,作用为打开一个文件,如果文件不存在且mode为写或追加时,文件将被创建。添加‘b’到mode参数中,将对文件以二进制形式操作。添加‘+’到mode参数中,将允许对文件同时进行读写操作 1、参数filename:文件名称。 2、参数mode:'r'(读)、'w'(写)、'a'(追加)。 3、参数bufsize:如果为0表示不进行缓冲,如果为1表示进行行缓冲,如果是一个大于1的数表示缓冲区的大小 。
input([prompt])  获取用户输入 推荐使用raw_input,因为该函数将不会捕获用户的错误输入
open(name[, mode[, buffering]])  打开文件 与file有什么不同?推荐使用open
print 打印函数
raw_input([prompt])  设置输入,输入都是作为字符串处理

8.3 重点掌握内置函数

  • map函数
 1 #有个需求,想把列表里的每个元素进行操作,并返回每个元素操作后的值,例如求每个元素平方的操作
 2 
 3 #一般方法,我们可以这样做
 4 li = [1,2,3,4,5]
 5 ret = []
 6 for i in li:
 7     ret.append(i*i)
 8 print(ret)
 9 #但是又想,这仅仅是一个列表,要是有很多列表,我们就得写很多循环,像这种实现一个特定的功能我们可以用函数试试~~~
10 li = [1,2,3,4,5]
11 def map_test(args):
12     ret = []
13     for i in args:
14         ret.append(i*i)
15     return ret
16 print map_test(li)
17 
18 #这样就实现了多个列表,每次传一个值就行了,但是又有问题了,需求不是把每个元素都平方,我们要把每个函数加1怎么办呢,我们又得写多个函数。
19 #这种我们可以用多个参数试试,一个参数是传入的函数,一个参数是传入的列表。
20 li = [1,2,3,4,5]
21 def add(x):
22     return x + 1
23 
24 def map_test(func,li):
25     ret = []
26     for i in li:
27         ret.append(func(i))
28     return ret
29 print map_test(add,li)
30 
31 #这样就完成了,每次传入一个函数和列表就可以计算。这时可以优化下函数,尽量减少代码,我们可以用匿名函数lambda。
32 
33 li = [1,2,3,4,5]
34 
35 def map_test(func,li):
36     ret = []
37     for i in li:
38         ret.append(func(i))
39     return ret
40 
41 print map_test(lambda x:x+1,li)
42 
43 # 这样就大大缩减了代码。
44 # 但是有个好消息,就是python中有一个内置的map函数,用来处理序列中的每个元素,得到的结果是一个"列表",该"列表"元素个数及位置与原来一样
45 li = [1,2,3,4,5]
46 
47 print map(lambda x:x+1,li)
map函数示例
  •  reduce函数
 1 #有个需求,相对一个序列里面的数值求和,例如对以下列表求和
 2 #一般方法,我们可以这样做
 3 num = [1,2,3,4,5]
 4 n = 0
 5 for i in num:
 6     n+=i
 7 print n
 8 
 9 #利用学习map的知识,我们知道,这里可以用两个参数传入的函数,一个参数是传入的函数。另一个是传入的列表。
10 num = [1,2,3,4,5]
11 def add(x,y):
12     return x+y
13 
14 def reduce_test(func,args):
15     res = num.pop(0)
16     for i in args:
17         res = func(res,i)
18     return res
19 
20 print reduce_test(add,num)
21 
22 #这里有个问题,我们计算的是1到5的和,有些时候用户会指定初始值,这里优化下。并把函数用匿名函数lambda优化。
23 num = [1,2,3,4,5]
24 def reduce_test(func,num,init=None):
25     if init is None:
26         res = num.pop(0)
27     else:
28         res = init
29     for i in num:
30         res=func(res,i)
31     return res
32 print(reduce_test(lambda x,y: x+y,num,100))   #这里的100是初始值,结果为115
33 
34 #大功告成。
35 
36 #但是有个好消息,就是python2.x中有一个内置的reduce函数,作用是处理一个序列,把序列进行合并操作。
37 num = [1,2,3,4,5]
38 print(reduce(lambda x,y: x+y,num,100))
39 
40 #注意:python3里面reduce被移除内置函数,我们可以用 from functools import reduce导入即可。
41 
42 reduce函数
reduce函数示例
  •  filter函数
 1 #有个需求,我们要把列表以'z'开头的元素过滤掉
 2 people = ['zhangsan','lisi','wangwu','zhaoliu']
 3 # 一般方法,我们可以这样做
 4 for i in people:
 5     if not i.startswith('z'):
 6         print i
 7 
 8 #利用学习map的知识,我们知道,这里可以用两个参数传入的函数,一个参数是传入的函数。另一个是传入的列表。
 9 people = ['zhangsan','lisi','wangwu','zhaoliu']
10 def guolv(x):
11     return x.startswith('z')
12 
13 def test_filter(func,args):
14     ret = []
15     for i in args:
16         if not func(i):
17             ret.append(i)
18     return ret
19 
20 print test_filter(guolv,people)
21 
22 #匿名函数优化
23 people = ['zhangsan','lisi','wangwu','zhaoliu']
24 def test_filter(func,args):
25     ret = []
26     for i in args:
27         if not func(i):
28             ret.append(i)
29     return ret
30 print test_filter(lambda x:x.startswith('z'),people)
31 
32 # 但是有个好消息,就是python中有一个内置的filter函数,遍历序列中的每个元素,判断每个元素得到的布尔值,如果是True则保留下来.
33 people = ['zhangsan','lisi','wangwu','zhaoliu']
34 print filter(lambda x:not x.startswith('z'),people)
filter函数示例

 

8.4 常用内置函数举例介绍

1 abs(-5)                          # 取绝对值,也就是5
2 round(2.6)                       # 四舍五入取整,也就是3.0
3 pow(2, 3)                        # 相当于2**3,如果是pow(2, 3, 5),相当于2**3 % 5
4 cmp(2.3, 3.2)                    # 比较两个数的大小
5 divmod(9,2)                      # 返回除法结果和余数
6 max([1,5,2,9])                   # 求最大值
7 min([9,2,-4,2])                  # 求最小值
8 sum([2,-1,9,12])                 # 求和
数学运算
1 int("5")                         # 转换为整数 integer
2 float(2)                         # 转换为浮点数 float
3 long("23")                       # 转换为长整数 long integer
4 str(2.3)                         # 转换为字符串 string
5 complex(3, 9)                    # 返回复数 3 + 9i
6 ord("A")                         # "A"字符对应的数值
7 chr(65)                          # 数值65对应的字符
8 unichr(65)                       # 数值65对应的unicode字符
类型转换
1 进制转换
2 bin(56)                          # 返回一个字符串,表示56的二进制数
3 hex(56)                          # 返回一个字符串,表示56的十六进制数
4 oct(56)                          # 返回一个字符串,表示56的八进制数
5 
6 真假性判断,在Python中,下列对象都相当于False: [], (), {}, 0, None, 0.0, ''
7 bool(0)                          # 转换为相应的真假值,在Python中,0相当于False
进制转换&bool
1 list((1,2,3))                    # 转换为表 list
2 tuple([2,3,4])                   # 转换为定值表 tuple
3 slice(5,2,-1)                    # 构建下标对象 slice
4 dict(a=1,b="hello",c=[1,2,3])    # 构建词典 dictionary
序列转换
1 all([True, 1, "hello!"])         # 是否所有的元素都相当于True值
2 any(["", 0, False, [], None])    # 是否有任意一个元素相当于True值
3 sorted([1,5,3])                  # 返回正序的序列,也就是[1,3,5]
4 reversed([1,5,3])                # 返回反序的序列,也就是[3,5,1]
序列操作
posted @ 2017-07-31 21:52  Mr.gaofubin  阅读(348)  评论(0编辑  收藏  举报