Python【第四篇】函数、内置函数、递归、装饰器、生成器和迭代器
一、函数
函数是指将一组语句的集合通过一个名字(函数名)封装起来,要想执行这个函数,只需调用其函数名即可
特性:
- 减少重复代码
- 使程序变的可扩展
- 使程序变得易维护
1.定义
- def 函数名(参数):
- ...
- 函数体
- ...
- 返回值
函数的定义主要有如下要点:
- def:表示函数的关键字
- 函数名:函数的名称,可根据函数名调用函数
- 函数体:函数中进行一系列的逻辑计算
- 参数:为函数体提供数据
- 返回值:当函数执行完毕后,可以给调用者返回数据。
2.参数
函数的有三种不同的参数:
- 普通参数(也称为位置参数)
- 默认参数
- 动态参数
普通参数
- #定义函数
- #n是函数name的形式参数,简称:形参
- def name(n):
- print(n) # jack
- #执行函数
- #'jack'是函数name的实际参数,简称:实参
- name('jack')
默认参数
- def func(name, age = 18):
- print("%s:%s"%(name,age))
- # 指定参数
- func('jack', 19) # 上面输出jack:19
- # 使用默认参数
- func('jack') # 上面输出jack:18
- 注:默认参数需要放在参数列表最后
动态参数(*args)
- def func(*args):
- print(args)
- # 执行方式一
- func(11,22,33,55,66) # 上面输出(11, 22, 33, 55, 66)
- # 执行方式二
- li = [11,22,33,55,66] # 上面输出(11, 22, 33, 55, 66)
- func(*li)
动态参数(**kwargs)
- def func(**kwargs):
- print(kwargs)
- # 执行方式一
- func(name='jack',age=18) # 上面输出{'name': 'jack', 'age': 18}
- # 执行方式二
- li = {'name':'jack', 'age':18, 'job':'pythoner'}
- func(**li) # 上面输出{'name': 'jack', 'age': 18, 'job': 'pythoner'}
参数顺序:位置参数、默认参数(即关键字参数,形参中如果默认参数后面有可变位置参数,实参中,这个默认参数不能写成关键字参数样式,只能写一个值,即位置参数的样子)、可变位置参数、可变关键字参数。
- def hi(a,*args,**kwargs):
- print(a,type(a)) # 11 <class 'int'>
- print(args,type(args)) # (22, 33) <class 'tuple'>
- print(kwargs,type(kwargs)) # {'k1': 'jack', 'k2': 'tom'} <class 'dict'>
- hi(11,22,33,k1='jack',k2='tom')
3.返回值
函数外部的代码要想获取函数的执行结果,就可以在函数里用return语句把结果返回。
- def stu_register(name, age, course='python' ,country='CN'):
- print("----注册学生信息------")
- print("姓名:", name)
- print("age:", age)
- print("国籍:", country)
- print("课程:", course)
- if age > 22:
- return False
- else:
- return True
- registriation_status = stu_register("老王",22,course="PY全栈开发",country='JP')
- if registriation_status:
- print("注册成功")
- else:
- print("too old to be a student.")
注意:
- 函数在执行过程中只要遇到return语句,就会停止执行并返回结果,所以也可以理解为 return 语句代表着函数的结束
- 如果未在函数中指定return,那这个函数的返回值为None
4.全局、局部变量
在函数中定义的变量称为局部变量,在程序的一开始定义的变量称为全局变量。
全局变量作用域是整个程序,局部变量作用域是定义该变量的函数。
当全局变量与局部变量同名时,在定义局部变量的函数内,局部变量起作用;在其它地方全局变量起作用。
全局变量在函数里可以随便调用,但要修改就必须用 global 声明
- # 全局变量
- P = 'jack'
- def name():
- global P # 声明修改全局变量
- P = 'jenny' # 局部变量
- print(P) # jenny
- def name2():
- print(P) # jenny
- name()
- name2() # jenny
二、内置函数
Python的内置函数有许多,如下图:
- # 匿名函数,冒号前面是形参,冒号后面是函数体,并将结果return到函数调用处
- f = lambda a, b: a + b
- print(f(2, 3)) # 5
- # abs() 取绝对值
- print(abs(-111)) # 111
- # all() 循环可迭代对象的每个元素,都为真则返回True,否则返回假
- # 0,None ,"",[],(),{} 是假的
- print(all([11, 22])) # True
- # any 有一个为真,全部都为真
- print(any([0, 0, None])) # False
- # bin 将十进制转换成2进制
- # oct() hex()
- print(bin(11)) # 0b1011
- # chr() 找到数字对应的ascii码
- # ord() ascii码对应的数字
- # chr ord 只适用于ascii码
- print(chr(65)) # A
- print(ord('A')) # 65
- # divmod 返回除法的(值,余数)
- print(divmod(10, 3)) # (3,1)
- # eval 计算器的功能 返回结果
- print(eval('a+60', {'a': 90})) # 150
- # exec,执行python代码,没有返回值
- exec("for i in range(5):print(i)") # 直接循环输出0,1,2,3,4
- # filter(函数,可迭代的对象)
- # 循环可以迭代的对象,传入函数中执行,如果不符合就过滤
- def fun(s): # 定义判断一个数是否是偶数的函数
- if s % 2 == 0:
- return True
- else:
- return False
- ret = filter(fun, [1, 2, 3, 4, 5, 6, 7, 8])
- for i in ret:
- print(i) # 打印出2,4,6,8
- # 用匿名函数改写一下
- ret1 = filter(lambda x: x % 2 == 0, [1, 2, 3, 4, 5, 6, 7, 8])
- for i in ret1:
- print(i) # 2,4,6,8
- # map将传入的函数依次作用到序列的每个元素,并把结果作为新的Iterator返回
- ret = map(lambda x: x + 100, [1, 2, 3])
- for i in ret:
- print(i) # 101,102,103
- # globals() 获取当前文件的所有全局变量
- # locals() 获取当前文件的所有局部变量
- # hash() 获取哈希值
- # isinstance 看某个对象是不是某个类创建的
- # iter() 创建一个可以被迭代的对象 next()取下一个值
- k = iter([1, 2, 3, 4])
- print(next(k)) # 1
- # pow() 求指数
- print(pow(2, 10)) # 1024
- # round() 四舍五入
- # zip
- l1 = [1, 2, 3, 4]
- l2 = ['a', 'b', 'c', 'd']
- k = zip(l1, l2)
- for i in k:
- print(i) # 打印出(1,a),(2,b)....
- a = [1, 2, 3, 4, 5]
- b = ['aaa', 'bbb', 'ccc', 'ddd']
- c = [111, 222, 333, 444]
- for i in zip(a, b, c):
- print(i)
- # (1, 'aaa', 111)
- # (2, 'bbb', 222)
- # (3, 'ccc', 333)
- # (4, 'ddd', 444)
- for i, j, k in zip(a, b, c):
- print(i, j, k)
- # 1 aaa 111
- # 2 bbb 222
- # 3 ccc 333
- # 4 ddd 444
- # zip应用
- for m, n in zip(title_list, content_list): # 把标题和图片对个对应
- print('正在下载>>>>>:' + m, n)
三、递归
- 递归就是在过程或函数里调用自身。
- 在使用递归策略时,必须有一个明确的递归结束条件,称为递归出口。
- 递归算法解题通常显得很简洁,但递归算法解题的运行效率较低。所以一般不提倡用递归算法设计程序。
- 在递归调用的过程当中系统为每一层的返回点、局部量等开辟了栈来存储。递归次数过多容易造成栈溢出等。所以一般不提倡用递归算法设计程序。
用递归写一个阶乘函数 f(n)算出n的阶乘
- def f(n):
- if n==0: # n=0的话直接返回空,对用户输入的零进行判断
- return None
- elif 1==n: # n=1的话就不再递归
- return n
- else:
- return n*f(n-1) # 递归在执行f(n-1) 直到f(1)
- print(f(5)) # 120
- '''
- f(5)的执行过程如下
- ===> f(5)
- ===> 5 * f(4)
- ===> 5 * (4 * f(3))
- ===> 5 * (4 * (3 * f(2)))
- ===> 5 * (4 * (3 * (2 * f(1))))
- ===> 5 * (4 * (3 * (2 * 1)))
- ===> 5 * (4 * (3 * 2))
- ===> 5 * (4 * 6)
- ===> 5 * 24
- ===> 120
- '''
利用函数编写如下数列:
斐波那契数列指的是这样一个数列 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233,377,610,987,1597,2584,4181,6765,10946,17711,28657,46368...
用递归获取斐波那契数列中的第10个数
- def fun(n): # fun(10)即可计算第十个斐波拉数
- if 1==n : # 直接定义前面两个数为 0 ,1,如果输入的n为1,2的话直接就返回了
- return 0
- elif 2==n:
- return 1
- else:
- return fun(n-1)+fun(n-2) #如果输入的不是1,2则进行递归出来计算他前面两个数的和
- '''
- fun(5)的执行过程如下(fun(10)的结果为34)
- ===> fun(5)
- ===> fun(4)+fun(3)
- ===> fun(3)+fun(2) + fun(2)+fun(1)
- ===> fun(2)+fun(1)+fun(2)+fun(2)+fun(1)
- ===> 1+0+1+1+1+0
- ===> 3
- '''
四、装饰器
本质是函数,装饰其它函数,为其它函数添加附加功能,原则:
- 不能修改被装饰函数的源代码
- 不能修改被装饰的函数的调用方式
装饰器对被装饰的函数是透明的,即:被装饰的函数感知不到装饰器的存在,因为没改函数的代码,运行方式也没变
装饰器执行顺序
- def login(func): # 1,3
- def inner(arg): # 4,7
- print('yanzheng') # 8
- func(arg) # 9
- return inner # 5
- @login # 2,10
- def tv(name):
- print('welcom %s' %name) # 11
- tv('wgy') # 6
统计函数执行时间
- import time
- def timmer(func):
- def warpper(*args, **kwargs):
- start_time = time.time()
- func()
- stop_time = time.time()
- print('the func run time is %s' %(stop_time-start_time))
- return warpper
- @timmer
- def test1():
- time.sleep(1)
- print('in the test1')
- test1()
五、生成器和迭代器
通过列表生成式,我们可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的list,从而节省大量的空间。在Python中,这种一边循环一边计算的机制,称为生成器:generator。要创建一个generator,有很多种方法。
第一种方法很简单,只要把一个列表生成式的[]
改成(),
就创建了一个generator:
- b = (i*2 for i in range(3)) # 列表生成式的[]改为(),就变成了生成器
- print(b)
- for i in b:
- print(i)
- '''
- <generator object <genexpr> at 0x00000000021DE8E0>
- 0
- 2
- 4
- '''
通过函数写生成器
函数中加yield(暂停),表示可以将函数变成生成器,调用函数时得到一个生成器,yield之后的代码不执行,yield就返回生成器地址,next调用生成器,可以像return一样,返回值,但是不会像return返回一次函数就终止了,而且是在执行过程中,可以多次将数据或者状态返回到next调用处(可以返回函数循环体中每次产生的值),如,读取一个大文件,一边读一边返回。此时脚本中的return信息只在抛出异常的时候打印。
- def fib(max):
- n, a, b = 0, 0, 1
- while n < max:
- print('before yield')
- # print(b)
- yield b # 把函数的执行过程冻结在这一步,并且把b的值返回给外面的next()
- a, b = b, a + b
- n = n + 1
- return 'done'
- f = fib(3) # 调用函数,将函数变成一个生成器,将地址返回给f
- print(f)
- print(f.__next__())
- print(next(f))
- print(f.__next__())
- print(next(f))
- '''
- <generator object fib at 0x0000000001E7E8E0>
- before yield
- 1
- before yield
- 1
- before yield
- 2
- Traceback (most recent call last):
- File "F:/test.py", line 15, in <module>
- print(next(f))
- StopIteration: done
- '''
迭代器
可以直接作用于for循环的数据类型有以下几种:
- 一类是集合数据类型,如list、tuple、dict、set、str等;
- 一类是generator,包括生成器和带yield的generator function。
可以被next()函数调用并不断返回下一个值的对象称为迭代器:Iterator。
注意区别:
可迭代对象:Iterable(可以直接作用于for循环)
迭代器:Iterator(可以被next()函数调用并不断返回下一个值)
生成器都是Iterator对象,但list、dict、str虽然是Iterable,却不是Iterator。把list、dict、str等Iterable变成Iterator可以使用iter()函数
- from collections import Iterator
- a = [1,2,3]
- b = iter(a)
- print(isinstance(b,Iterator))
- print(b.__next__())
- print(b.__next__())
- print(b.__next__())
- print(b.__next__())
- '''
- True
- 1
- 2
- 3
- Traceback (most recent call last):
- File "F:/test.py", line 8, in <module>
- print(b.__next__())
- StopIteration
- '''
六、练习题(参考答案已放在Q群文件中)
1.写一个range功能的生成器
Python【第四篇】函数、内置函数、递归、装饰器、生成器和迭代器的更多相关文章
- python 基础篇 15 内置函数和匿名函数
------------------------>>>>>>>>>>>>>>>内置函数<<< ...
- Python第七天 函数 函数参数 函数里的变量 函数返回值 多类型传值 函数递归调用 匿名函数 内置函数
Python第七天 函数 函数参数 函数里的变量 函数返回值 多类型传值 函数递归调用 匿名函数 内置函数 目录 Pycharm使用技巧(转载) Python第一天 ...
- python基础12_匿名_内置函数
一个二分查找的示例: # 二分查找 示例 data = [1, 3, 6, 7, 9, 12, 14, 16, 17, 18, 20, 21, 22, 23, 30, 32, 33, 35, 36, ...
- 【python】dir(__builtins__)查看python中所用BIF(内置函数)
dir(__builtins__)查看python中所用BIF(内置函数)
- python全栈开发-Day13 内置函数
一.内置函数 注意:内置函数id()可以返回一个对象的身份,返回值为整数. 这个整数通常对应与该对象在内存中的位置,但这与python的具体实现有关,不应该作为对身份的定义,即不够精准,最精准的还是以 ...
- 查看python内部模块命令,内置函数,查看python已经安装的模块命令
查看python内部模块命令,内置函数,查看python已经安装的模块命令 可以用dir(modules) 或者用 pip list或者用 help('modules') 或者用 python -m ...
- python 匿名函数&内置函数
匿名函数:为了解决那些功能很简单的需求而设计的一句话函数怎么定义匿名函数: cal = lambda x : x*x # cal是函数名,lambda是定义匿名函数的关键字 冒号前面的额x是参数即函数 ...
- Python学习(八) —— 内置函数和匿名函数
一.递归函数 定义:在一个函数里调用这个函数本身 递归的最大深度:997 def func(n): print(n) n += 1 func(n) func(1) 测试递归最大深度 import sy ...
- python成长之路八 -- 内置函数
1,python内置函数 内置函数 abs() dict() help() min() setattr() all() dir() hex() next() slice() a ...
- python学习 day013打卡 内置函数
本节主要内容: 内置函数: 内置函数就是python给你提供的.拿来直接用的函数,比如print,input等等.截止到python版本3.6.2 python一共提供了68个内置函数.他们就是pyt ...
随机推荐
- Java实现栈数据结构
栈(英语:stack)又称为栈或堆叠,是计算机科学中一种特殊的串列形式的抽象数据类型,其特殊之处在于只能允许在链表或数组的一端(称为堆栈顶端指针,英语:top)进行加入数据(英语:push)和输出数据 ...
- 基于raspberry搭建个人web server
树莓派系统介绍 安装操作系统及网络\远程控制配置 安装常用软件 构建web服务器(nginx + php + sqlite) 构建web服务器(appach+mysql+php) 构建NAS服务器 其 ...
- Linux系统下virtuoso数据库安装与使用
最近在调研关联数据的一些东西,需要用到rdf数据库,所以接触了virtuoso数据库.安装的坑其实并不多,之前在windows 10上安过一次.这次在ubuntu 18.04上安装一下,其他的linu ...
- SQL语句更新时间字段的年份、月份、天数、时、分、秒
SQL语句更新时间字段的年份.月份.天数.时.分.秒 --修改d表日期字段的年份update dset birth=STUFF(convert(nvarchar(23),birth,120),1,4, ...
- python 迭代器协议和生成器
一.什么是迭代器协议 1.迭代器协议是指:对象必须提供一个next方法,执行该方法要么返回迭代中的下一项,要么就引起一个stoplteration异常,以终止迭代(只能往后走,不能往前退) 2.可迭代 ...
- User Agent 大全
一.基础知识篇: Http Header之User-Agent User Agent中文名为用户代理,是Http协议中的一部分,属于头域的组成部分,User Agent也简称UA.它是一个特殊字符串头 ...
- Linux中删除特殊名称文件的多种方式
今日分享:我们在肉体的疾病方面花了不少钱,精神的病害方面却没有花什么,现在已经到了时候,我们应该有不平凡的学校.--<瓦尔登湖> 前言 我们都知道,在linux删除一个文件可以使用rm命令 ...
- hashCode()方法对HashMap的性能影响
HashMap的put()方法会比较key的hash值,key的hash值获取方式如下: //HashMap的put方法 public V put(K key, V value) { return p ...
- 模块简介:(logging)(re)(subprocess)
''' logging模块: logging的日志可以分为 debug():Detailed information, typically of interest only when diagnosi ...
- 微信小程序设置域名、不校验域名
设置--项目设置 将不校验域名勾上就可以了,不再校验域名了通过 url: 'https://localhost:8443/spring4/user/list.do',就可以访问后台了. 若要配置域名则 ...