前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >python3–函数

python3–函数

作者头像
老七Linux
发布2018-05-09 17:19:48
1.7K0
发布2018-05-09 17:19:48
举报

函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段。

函数能提高应用的模块性,和代码的重复利用率。

任何一个比较牛逼的程序均由多个函数封装而成。

定义一个函数

你可以定义一个由自己想要功能的函数,以下是简单的规则:

  • 函数代码块以 def 关键词开头,后接函数标识符名称和圆括号 ()。
  • 任何传入参数和自变量必须放在圆括号中间,圆括号之间可以用于定义参数。
  • 函数的第一行语句可以选择性地使用文档字符串—用于存放函数说明。
  • 函数内容以冒号起始,并且缩进。
  • return [表达式] 结束函数,选择性地返回一个值给调用方。不带表达式的return相当于返回 None。
语法

Python 定义函数使用 def 关键字,一般格式如下:

代码语言:javascript
复制
def 函数名(参数列表):
    函数体

例如:

代码语言:javascript
复制
def helloworld()
    print("hello world")
    
helloworld()

输出:
hello world

再来个实例:

代码语言:javascript
复制
def fun(a, *hehe, **hahaha):
    print("{0}--{1}--{2}".format(a, hehe, hahaha))

fun(1,2,3,4,5,x=1,y=2)

输出:
1--(2, 3, 4, 5)--{'x': 1, 'y': 2}

分析:

我使用了–来分割,可以看出来其中的赋值如下:

代码语言:javascript
复制
a = 1
hehe = 2, 3, 4, 5   tuple 一一对应过来
hahaha ={"x": 1, "y": 2}   dict  一一对应过来

也就是:

代码语言:javascript
复制
*xxx     一个 * 代表  →   tuple

**xxx    两个 ** 代表  →  dict
匿名函数:
代码语言:javascript
复制
def plus(a,b,c):
    return a+b+c
print(plus(1,2,3))


## 匿名函数
aa = lambda x,y,z:x+y+z

print(aa(3,3,3))


输出:
6
9

注意观察上面的Python示例代码,f = lambda x,y,z:x+y+z 中的关键字lambda表示匿名函数,

代码语言:javascript
复制
# 冒号:之前的x,y,z表示它们是这个函数的参数。
# 匿名函数不需要return来返回值,表达式本身结果就是返回值。
无参数匿名函数:
代码语言:javascript
复制
t = lambda : True
print (t)

输出:
True
默认参数:
代码语言:javascript
复制
lambda x,y=3: x*y #允许参数存在默认值
代码语言:javascript
复制
a = lambda *z:z #*z返回的是一个元祖


print(a('Testing1','Testing2'))

输出:
('Testing1', 'Testing2')

再次反过来看下之前的阶乘题目:

代码语言:javascript
复制
def jc(n):
    sum = 1
    if n == 1:
        return sum
    else:
        for i in range(1, int(n)+1):
            sum *= i
        return sum

def main():
    sumt = 0
    number = input("pls input a number: ")
    for i in range(0, int(number)+1):
        sumt += jc(i)
    print(sumt)

if __name__ == '__main__':
    main()

分析一下:

main()主函数调用 main()函数,main()函数再次调用jc()

练习题Ⅱ:
代码语言:javascript
复制
def f(x,l=[]):
    for i in range(x):
        l.append(i*i)
    print (l)

f(2)
f(3,[3,2,1])
f(3)

分析如上程序的输出结果是?

分析:

代码语言:javascript
复制
##申明一个函数,第一个参数是整形,第二个参数是list
##l的默认值是空

也就是说当传入的参数为2的时候此时的l值为空,输出的值为

代码语言:javascript
复制
[0, 1]

但是当x传入3,l传入[3,2,1]的时候,输出为:

代码语言:javascript
复制
[3,2,1,0,1,2]

当x传入3的时候,输出按照我们直接的想法是:

代码语言:javascript
复制
[0,1,2]

但是这个值是错误的,当我们传入x的值的时候,其中在上层循环中l的值也没有消失,也还在内存当中,所以也会再次传入这个循环当中:

  • 第一轮循环的l列表值一直存在内存中:
  • 第二轮是有新的赋值,所以会采用新的赋值:
  • 第三轮l是没有赋值的,程序就会找到内存中l的现值并赋值:
代码语言:javascript
复制
[0,1,0,1,4]

函数的几个关键字:

代码语言:javascript
复制
def     定义函数
return     返回值
pass       略过此句,继续执行pass下面的任何语句
exit(1)        直接退出,并返回状态码 1

高阶函数

map()

实例:

代码语言:javascript
复制
def f(x):
    return x*x

aa = map(f,[0,1,2,3])

print(aa)

输出:
<map object at 0x04EB22D0>

输出的是一个map类型

如何直接将结果打印出来?

代码语言:javascript
复制
def f(x):
    return x*x

aa = map(f,[0,1,2,3])

print(list(aa))

输出:
[0, 1, 4, 9]

强制的将输出结果转化为list结构。

返回值
代码语言:javascript
复制
Python 2.x 返回列表。

Python 3.x 返回迭代器。

实例展示了 map() 的使用方法:

代码语言:javascript
复制
实例1:
def  squar(x):
    return x ** 2

print(list(map(squar, [1, 2, 3, 4, 5])))

实例2:
print(list(map(lambda x: x ** 2, [1, 2, 3, 4, 5])))

不难看出,两个程序其实是一个意思,输出结果均为:

代码语言:javascript
复制
[1, 4, 9, 16, 25]
[1, 4, 9, 16, 25]
提供了两个列表,对相同位置的列表数据进行相加
代码语言:javascript
复制
map(lambda x, y: x + y, [1, 3, 5, 7, 9], [2, 4, 6, 8, 10])

输出:
[3, 7, 11, 15, 19]

map()作为高阶函数,事实上它把运算规则抽象了,因此,我们不但可以计算简单的f(x)=x2,还可以计算任意复杂的函数,比如,把这个list所有数字转为字符串:

只需要一行代码:

代码语言:javascript
复制
list(map(str, [1, 2, 3, 4, 5, 6, 7, 8, 9]))

['1', '2', '3', '4', '5', '6', '7', '8', '9']
reduce()

reduce把一个函数作用在一个序列[x1, x2, x3, …]上,这个函数必须接收两个参数,reduce把结果继续和序列的下一个元素做累积计算,其效果就是:

代码语言:javascript
复制
reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)

实例一、

代码语言:javascript
复制
from functools import reduce

def add(x, y):
    return x + y

print(reduce(add, [1, 2, 3, 4]))

输出:
10

当然求和运算可以直接用Python内建函数sum(),没必要动用reduce。

但是如果要把序列[1, 3, 5, 7, 9]变换成整数13579,reduce就可以派上用场:

代码语言:javascript
复制
from functools import reduce

def add(x, y):
    return x * 10 + y

print(reduce(add, [1, 3, 5, 7, 9]))

输出:
13579

再次根据如上的操作,利用map函数把str转换为int:

代码语言:javascript
复制
from functools import reduce

def num(y, z):
    return y * 10 + z

def charac(x):
    digits = {'0':0, '1':1, '2':2, '3':3, '4':4, '5':5, '6':6, '7':7, '8':8, '9':9}
    return digits[x]

print(reduce(num, map(charac, '13579')))

输出:
13579
filter()

Python内建的filter()函数用于过滤序列。

和map()类似,filter()也接收一个函数和一个序列。和map()不同的是,filter()把传入的函数依次作用于每个元素,然后根据返回值是True还是False决定保留还是丢弃该元素。

例如,在一个list中,删掉奇数,只保留偶数,可以这么写:

代码语言:javascript
复制
def isos(x):
    return x % 2 == 0  

print(list(filter(isos, [1, 2, 3, 5, 7, 8, 10])))

输出:
[2, 8, 10]

去空格:

代码语言:javascript
复制
def isos(x):
    return x and x.strip()

print(list(filter(isos, ['A', ' ', 'B', ' ', 'BC', 'AS'])))

输出:
['A', 'B', 'BC', 'AS']

可见用filter()这个高阶函数,关键在于正确实现一个“筛选”函数。

注意到filter()函数返回的是一个Iterator,也就是一个惰性序列,所以要强迫filter()完成计算结果,需要用list()函数获得所有结果并返回list。

sorted()
排序算法

排序是在程序中经常用到的算法。无论使用冒泡排序还是快速排序,排序的核心是比较两个元素的大小。如果是数字,我们可以直接比较,但如果是字符串或者两个dict呢?直接比较数学上的大小是没有意义的,因此,比较的过程必须通过函数抽象出来。

Python内置的sorted()函数就可以对list进行排序:

代码语言:javascript
复制
>>> sorted([36, 5, -12, 9, -21])
[-21, -12, 5, 9, 36]

此外,sorted()函数也是一个高阶函数,它还可以接收一个key函数来实现自定义的排序,例如按绝对值大小排序:

代码语言:javascript
复制
>>> sorted([36, 5, -12, 9, -21], key=abs)
[5, 9, -12, -21, 36]

key指定的函数将作用于list的每一个元素上,并根据key函数返回的结果进行排序。对比原始的list和经过key=abs处理过的list:

代码语言:javascript
复制
list = [36, 5, -12, 9, -21]

keys = [36, 5,  12, 9,  21]

然后sorted()函数按照keys进行排序,并按照对应关系返回list相应的元素:

代码语言:javascript
复制
keys排序结果 => [5, 9,  12,  21, 36]
                |  |    |    |   |
最终结果     => [5, 9, -12, -21, 36]

我们再看一个字符串排序的例子:

代码语言:javascript
复制
>>> sorted(['bob', 'about', 'Zoo', 'Credit'])
['Credit', 'Zoo', 'about', 'bob']

默认情况下,对字符串排序,是按照ASCII的大小比较的,由于’Z’ < ‘a’,结果,大写字母Z会排在小写字母a的前面。

现在,我们提出排序应该忽略大小写,按照字母序排序。要实现这个算法,不必对现有代码大加改动,只要我们能用一个key函数把字符串映射为忽略大小写排序即可。忽略大小写来比较两个字符串,实际上就是先把字符串都变成大写(或者都变成小写),再比较。

这样,我们给sorted传入key函数,即可实现忽略大小写的排序:

代码语言:javascript
复制
>>> sorted(['bob', 'about', 'Zoo', 'Credit'], key=str.lower)
['about', 'bob', 'Credit', 'Zoo']

要进行反向排序,不必改动key函数,可以传入第三个参数reverse=True

代码语言:javascript
复制
>>> sorted(['bob', 'about', 'Zoo', 'Credit'], key=str.lower, reverse=True)
['Zoo', 'Credit', 'bob', 'about']

对列表中的元素按名字排序排序:

代码语言:javascript
复制
L = [('Bob', 75), ('Adam', 92), ('Bart', 66), ('Lisa', 88)]

aa = sorted(L, key=lambda x:x[0])

print(aa)
输出:
[('Adam', 92), ('Bart', 66), ('Bob', 75), ('Lisa', 88)]

再按成绩从高到低排序:

代码语言:javascript
复制
L = [('Bob', 75), ('Adam', 92), ('Bart', 66), ('Lisa', 88)]

aa = sorted(L, key=lambda x:x[1])

print(aa)

输出:
[('Bart', 66), ('Bob', 75), ('Lisa', 88), ('Adam', 92)]

实例2:

对字典dict(a=10, c=22, d=33, b=11)进行排序:

代码语言:javascript
复制
m = dict(a=10, c=22, d=33, b=11)

print(sorted(m.items()))

输出:
m = dict(a=10, c=22, d=33, b=11)

要是根据值来排序呢?

代码语言:javascript
复制
m = dict(a=10, c=22, d=33, b=11)

print(sorted(m.items(), key=lambda x:x[1]))

输出:
[('a', 10), ('b', 11), ('c', 22), ('d', 33)]
生成器 && 生成器

通过列表生成式,我们可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。

所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的list,从而节省大量的空间。在Python中,这种一边循环一边计算的机制,称为生成器:generator。

要创建一个generator,有很多种方法。第一种方法很简单,只要把一个列表生成式的[]改成(),就创建了一个generator:

代码语言:javascript
复制
aa = [i for i in range(10)]
print(aa)
输出:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

或者求10以内数的平方:

代码语言:javascript
复制
aa = [i*i for i in range(10)]
print(aa)
输出:
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
生成器:

仔细看如下代码:

代码语言:javascript
复制
aa = [i*i for i in range(10)]
print(aa)

bb = (i*i for i in range(10))
print(bb)

输出:
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
<generator object <genexpr> at 0x0517F2D0>

创建aa和bb的区别仅在于最外层的[]和()aa是一个list,而bb是一个generator。

我们可以直接打印出list的每一个元素,但我们怎么打印出generator(生成器)的每一个元素呢?

如果要一个一个打印出来,可以通过for循环获得generator的返回值:

代码语言:javascript
复制
bb = (i*i for i in range(10))

for i in bb:
    print(i)

输出:
0
1
4
9
16
25
36
49
64
81

next()函数用法:

python3可以直接调取next函数

代码语言:javascript
复制
aa = (x for x in range(10) if x%2==0)

print(next(aa))
print(next(aa))
print(next(aa))
print(next(aa))
输出:
0
2
4
6
return和 yield的区别:
代码语言:javascript
复制
return:是用来返回具体的某个值;当执行到return,后续的逻辑代码不在执行。

yield:一般与循环一起用,相当于生成了一个容器(常见的就是字典);当执行到yield后,还会继续执行下面的逻辑代码。

实例:

代码语言:javascript
复制
针对/etc/passwd 列表中的内容按照uid排序:
代码语言:javascript
复制
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 4/13/2018 4:55 PM
# @Author  : zhdya
# @File    : demon2.py

import codecs

'''
/etc/passwd   查找用户,对用户优先级进行排序
'''
with codecs.open("passwd.sh", "r") as f:
    result = sorted(f.readlines(), key=lambda x: int(x.split(':')[2]))

with codecs.open("sortPasswd", "w") as f:
    f.writelines(result)

分析:

代码语言:javascript
复制
》》 首先需要打开文件的内容;
》》 选择分隔符;
》》 选择每行的uid进行排序;
》》 按照原理是已经可以排序了,但是最终排序下来是按照ascall来排序的;
》》 转变类型
》》 写入一个文件进行检查
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2017/04/16,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 定义一个函数
  • 语法
  • 匿名函数:
    • 无参数匿名函数:
      • 默认参数:
        • 练习题Ⅱ:
        • 高阶函数
          • map()
            • 返回值
            • 提供了两个列表,对相同位置的列表数据进行相加
          • reduce()
            • filter()
              • sorted()
                • 排序算法
              • 生成器 && 生成器
                • 生成器:
              • return和 yield的区别:
              相关产品与服务
              容器服务
              腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档