1、函数的嵌套

函数的嵌套调用:在调用一个函数的过程中,又调用了其它函数

示例1:

def bar():print('from nbar')def foo():print('from foo')bar()
foo()
#执行结果为
C:\Users\Administrator\AppData\Local\Programs\Python\Python36\python.exe C:/Users/Administrator/PycharmProjects/python18/day4/函数嵌套.py
from foo
from nbar

示例2:求函数所带四个参数的最大值

def max2(x,y):if x > y:return xelse:return ydef max4(a,b,c,d):res1=max2(a,b)res2=max2(res1,c)res3=max2(res2,d)return res3
print(max(1,2,3,-1))#执行结果如下
C:\Users\Administrator\AppData\Local\Programs\Python\Python36\python.exe C:/Users/Administrator/PycharmProjects/python18/day4/函数嵌套.py
3

函数的嵌套定义:在一个函数的内部,又定义另外一个函数

2、名称空间和作用域

名称空间:存放名字的地方,准确的说名称空间是存放名字与变量值绑定关系的地方名称空间共有三种名称空间既:  1、内置名称空间:在python解释器启动时产生,存放一些python内置的名字  2、全局名称空间:在执行文件时产生,存放文件级别定义的名字  3、局部名称空间:在执行文件的过程中,如果调用了函数,则会产生该函数的局部名称空间,用来存放该函数内定义的名字,该名字在函数调用时生效,在函数调用结束后失效

加载顺序:内置===》全局===》局部

优先掌握一:名字的查找顺序是:局部==》全局===》内置

作用域:作用的范围全局作用域:全局存货,全局有效:globals()

局部作用域:临时存活,局部生效:locals()
x=11111111111111111111111111111111111111111111# def f1():
#     x=1
#     y=2
#     def f2():pass
#     # print(locals())
#     print(globals())
#
# f1()
# print(locals() is globals())
# print(locals())
#
# print(dir(globals()['__builtins__']))#global nonlocal掌握
# x=1
# def f1():
#     global x
#     x=2
#
# f1()
# print(x)# l=[]
# def f2():
#     l.append('f2')
#
# f2()
# print(l)# x=0
# def f1():
#     # x=1
#     def f2():
#         # x=2
#         def f3():
#            # global x
#            nonlocal x
#            x=3
#         f3()
#         # print(x)
#     f2()
#     print(x)
# f1()
# print(x)

 

优先掌握二:作用域关系,在函数定义时就已经固定,于调用位置无关,在调用函数时,必须必须必须回到函数原来定义的位置去找作用域关系

x=1
def  f1():def f2():print(x)return f2# func=f1()
# print(func)
# x=10000000
# func()
# x=10000000def foo(func):x=300000000func() #f2()
x=10000000000000000000000foo(f1())
# x=10000000000000000000000
# foo(f1())

  

3、闭包函数

1. 定义在函数内部的函数
2. 包含对外部作用域名字的引用,而不是对全局作用域名字的引用,那么该内部函数就称为闭包函数

# x=1
# def  f1():
#     x=11111111111
#     def f2():
#         print(x)
#     return f2
#
# func=f1()# x=1000
# func()# def foo():
#     x=12312312312312312312312312312312312313123
#     func()
#
#
# foo()# def deco():
#     x=123123123123
#     def wrapper():
#         print(x)
#     return wrapper
#
# func=deco()# func()

闭包函数的应用:惰性计算

import requests #pip3 install requests# def get(url):
#     return requests.get(url).text
#
# print(get('https://www.python.org'))
# print(get('https://www.python.org'))
# print(get('https://www.python.org'))
# print(get('https://www.python.org'))# def index(url):
#     # url='https://www.python.org'
#     def get():
#         # return requests.get(url).text
#         print(requests.get(url).text)
#
#     return get
#
# python_web=index('https://www.python.org')
# baidu_web=index('https://www.baidu.com')# python_web()
# baidu_web()name='egon'
def index(url):x=1y=2def wrapper():# x# y# return requests.get(url).textprint(name)return wrapperpython_web=index('https://www.python.org')# print(python_web.__closure__[0].cell_contents)
print(python_web.__closure__)
# print(python_web.__closure__[0].cell_contents)
# print(python_web.__closure__[1].cell_contents)
# print(python_web.__closure__[2].cell_contents)

4、装饰器 

1、 开放封闭原则:对扩展是开放的,对修改是封闭

2、 装饰器:装饰它人的工具,装饰器本身可以是任意可调用对象,被装饰的对象本身也可以是任意可调用对象
  2.1 装饰器的遵循的原则:

    2.1.1、 不修改被装饰对象的源代码

    2.1.2、 不修改被调用对象的调用方式

装饰器名,必须写在被装饰对象的正上方,并且是单独一行

import timedef timmer(func):# func=indexdef wrapper():start=time.time()func()stop=time.time()print('run time is %s' %(stop-start))return wrapper@timmer # index=timmer(index)
def index():time.sleep(3)print('welcome to index')
@timmer # home=timmer(home)
def home():time.sleep(2)print('welcome to home page')index()
home()  

装饰器补充

#补充一:wraps# import time
# from functools import wraps
#
# def timmer(func):
#     @wraps(func)
#     def wrapper(*args,**kwargs):
#         start=time.time()
#         res=func(*args,**kwargs)
#         stop=time.time()
#         print('run time is %s' %(stop-start))
#         return res
#     return wrapper
#
#
# @timmer # index=timmer(index)
# def index():
#     '''这是index函数'''
#     time.sleep(3)
#     print('welcome to index')
#     return 123
#
# print(index.__doc__)
# # print(help(index))

#补充二:一个函数头顶上可以多个装饰器
import time
from functools import wraps
current_user={'user':None}def timmer(func):@wraps(func)def wrapper(*args,**kwargs):start=time.time()res=func(*args,**kwargs)stop=time.time()print('run time is %s' %(stop-start))return resreturn wrapper
def auth(auth_type='file'):def deco(func):def wrapper(*args, **kwargs):if auth_type == 'file':if current_user['user']:return func(*args, **kwargs)name = input('name: ').strip()password = input('password: ').strip()with open('db.txt', encoding='utf-8') as f:user_dic = eval(f.read())if name in user_dic and password == user_dic[name]:res = func(*args, **kwargs)current_user['user'] = namereturn reselse:print('user or password error')elif auth_type == 'mysql':print('mysql')elif auth_type == 'ldap':print('ldap')else:print('not valid auth_type')return wrapperreturn deco@timmer #index=timmer(wrapper)
@auth() # @deco #index=deco(index) #wrapper
def index():'''这是index函数'''time.sleep(3)print('welcome to index')return 123# print(index.__doc__)
# print(help(index))index()

  

5、生成器

学习生成器之前,我们先来看看什么是列表生成式

#列表生成式
b = [ i*2 for i in range(10)]
print(b)###########打印输出###########
#[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]

通过列表生成式,我们可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,还需要花费很长时间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的list,从而节省大量的空间。在Python中,这种调用时才会生成相应数据的机制,称为生成器:generator

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

#生成器
l = [ i*2 for i in range(10)]
print(l)g = (i*2 for i in range(10))
print(g)###########打印输出###########
#[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
#<generator object <genexpr> at 0x0064AAE0>

print(g) 打印出来的信息显示g是一个生成器,创建lg的区别仅在于最外层的[]()l是一个list,而g是一个generator;我们可以直接打印出list的每一个元素,但我们怎么打印出generator的每一个元素呢?如果要一个一个打印出来,可以通过next()函数获得generator的下一个返回值

#生成器next打印
print(next(g))
#.........                 不断next 打印10次
#..........
print(next(g))###########打印输出###########
#0
#........
#18
#Traceback (most recent call last):
#  File "<stdin>", line 1, in <module>
#StopIteration

我们讲过,generator保存的是算法,每次调用next(g),就计算出g的下一个元素的值,直到计算到最后一个元素,没有更多的元素时,抛出StopIteration的错误。

上面这种不断调用next(g)实在是太变态了,正确的方法是使用for循环,因为generator也是可迭代对象,所以,我们创建了一个generator后,基本上永远不会调用next(),而是通过for循环来迭代它,并且不需要关心StopIteration的错误

#生成器for调用
g = (i*2 for i in range(10))        #不用担心出现StopIteration错误
for i in g:print(i)###########打印输出###########
# 0
# 2
# 4
# 6
# 8
# 10
# 12
# 14
# 16
# 18

generator非常强大。如果推算的算法比较复杂,用列表生成式转换的生成器无法去实现时,我们还可以用函数来实现。比如,著名的斐波拉契数列(Fibonacci)  

#函数表示斐波拉契数列
def fib(max):n, a, b = 0, 0, 1while n < max:print(b)a, b = b, a + bn += 1return 'done'fib(5)
###########打印输出###########
# 1
# 1
# 2
# 3
# 5

仔细观察,可以看出,fib函数实际上是定义了斐波那契数列的推算规则,可以从第一个元素开始,推算出后续任意的元素,这种逻辑其实非常类似generator;也就是说,上面的函数和generator仅一步之遥,那我们能不能把上面的函数变成一个生成器呢?  

#斐波拉契数列转换为generator
def fib(max):n, a, b = 0, 0, 1while n < max:#print(b)yield ba, b = b, a + bn += 1return 'done'print(type(fib(5)))     #打印fib(5)的类型
for i in fib(5):        #for循环去调用print(i)
###########打印输出###########
# <class 'generator'>
# 1
# 1
# 2
# 3
# 5

要把fib函数变成generator,只需要把print(b)改为yield b就可以了,这就是定义generator的另一种方法。如果一个函数定义中包含yield关键字,那么这个函数就不再是一个普通函数,而是一个generator

但是用for循环调用generator时,会发现拿不到generator的return语句的返回值,也就是return的值没有打印出来,现在我们来看看怎么去打印generator的返回值

#获取generator的返回值
def fib(max):n, a, b = 0, 0, 1while n < max:#print(b)yield ba, b = b, a + bn += 1return 'done'g = fib(5)
while True:try:x = next(g)print( x)except StopIteration as e:print(e.value)break
###########打印输出###########
# 1
# 1
# 2
# 3
# 5
# done

如果想要拿到返回值,必须捕获StopIteration错误,返回值包含在StopIterationvalue中,关于如何捕获错误,后面的错误处理还会详细讲解。 

还可通过yield实现在单线程的情况下实现并发运算的效果

import time
def consumer(name):print("%s 准备吃包子啦!" %name)while True:baozi = yieldprint("包子[%s]来了,被[%s]吃了!" %(baozi,name))def producer(name):c = consumer('A')c2 = consumer('B')c.__next__()        #c.__next__()等同于next(c)c2.__next__()print("老子开始准备做包子啦!")for i in range(10):time.sleep(1)print("%s做了2个包子!"%(name))c.send(i)c2.send(i)producer("lzl")

  

6、迭代器  

迭代:是一个重复的过程,每一次重复,都是基于上一次的结果而来  

# while True: #单纯的重复
#     print('你瞅啥')# l=['a','b','c','d']
# count=0
# while count < len(l):
#     print(l[count])
#     count+=1dic={'name':'egon','sex':'m',"age":18} #上述按照索引的取值方式,不适于没有索引的数据类型

迭代器:
可迭代对象iterable:凡是对象下有__iter__方法:对象.__iter__,该对象就是可迭代对象

# s='hello'
# l=['a','b','c','d']
# t=('a','b','c','d')
# dic={'name':'egon','sex':'m',"age":18}
# set1={1,2,3}
# f=open('db.txt')# s.__iter__()
# l.__iter__()
# t.__iter__()
# dic.__iter__()
# set1.__iter__()
# f.__iter__()

迭代器对象:可迭代对象执行内置的__iter__方法,得到的结果就是迭代器对象  

# dic={'name':'egon','sex':'m',"age":18}
#
# i=dic.__iter__()
# # print(i) #iterator迭代器
#
# # i.__next__() #next(i)
# print(next(i))
# print(next(i))
# print(next(i))
# print(next(i)) #StopIteration
#
# l=['a','b','c','d']
#
# i=l.__iter__()
# print(next(i))
# print(next(i))
# print(next(i))
# print(next(i))
# print(next(i)) #StopIteration

不依赖于索引的取值方式  

# l=['a','b','c','d']
# dic={'name':'egon','sex':'m',"age":18}
# iter_l=iter(l)
# iter_dic=iter(dic)
# while True:
#     try:
#         # print(next(iter_l))
#         k=next(iter_dic)
#         print(k,dic[k])
#     except StopIteration:
#         break

什么是迭代器对象:
1 有__iter__,执行得到仍然是迭代本身
2 有__next__

  

迭代器对象的优点
1:提供了一种统一的(不依赖于索引的)迭代方式
2:迭代器本身,比起其他数据类型更省内存

# l=['a','b','c','d']
# i=iter(l)# dic={'a':1,'b':2}
# x=dic.keys()
# print(x)
# i=x.__iter__()
#
# with open('a.txt') as f:
#     # print(next(f))
#     # print(next(f))
#     # print(next(f))
#     f.read()

迭代器对象的缺点
1:一次性,只能往后走,不能回退,不如索引取值灵活
2:无法预知什么时候取值结束,即无法预知长度

# l=['a','b','c','d']
# i=iter(l)
# print(next(i))
# print(next(i))
# print(next(i))

转载于:https://www.cnblogs.com/junxun/p/7224615.html

第四篇: python函数续相关推荐

  1. Python学习笔记(四)Python函数

    (三)python 函数 一 函数简介 在日常开发中有很多代码需要在多处使用 , 为了提高代码的复用性可以把代码需要复用的代码以函数的形式进行封装 . 二. 函数的调用 Python中内置了很多的函数 ...

  2. 第四课.Python函数(一)

    目录 函数的定义 注释增强与函数对象 栈与栈帧(Stack Frame) 函数的参数 偏函数 LEGB访问规则 函数的定义 大一学C语言时,老师说函数就是一个功能,后来学习C#后,老师却把函数又叫做方 ...

  3. C语言学习——从零开始学编程(第四篇:函数)

    目录 前言--小颖的话 一.函数的概念 二.C语言中函数的分类 1.库函数 1.自定义函数 1)函数名 2)函数返回值 3)函数参数 4)实现几个简单函数 三.函数的形参与实参 1.实际参数 2.形式 ...

  4. 四、Python函数

    4. 函数 官方文档 4.1 内置函数 中文博客 id name message 1 abs(num) 求绝对值 2 all(ite) 接受一个迭代器,所有元素都为真,返回True,否则False 3 ...

  5. 第四篇 Python循环

    While 循环 For 循环 转载于:https://www.cnblogs.com/victorm/p/9078215.html

  6. 最简单人工智能python_Python人工智能之路 - 第四篇 : jieba gensim 最好别分家之最简单的相似度实现...

    简单的问答已经实现了,那么问题也跟着出现了,我不能确定问题一定是"你叫什么名字",也有可能是"你是谁","你叫啥"之类的,这就引出了人工智能 ...

  7. 学Python 函数从青铜到王者

    文章目录 Python 入门第三天 Python 函数入门 1.函数定义 2.函数调用 3.函数的命名规则 4.函数的参数 5. 函数的作用域 Python 高级函数 1.嵌套函数 2.装饰器之不带参 ...

  8. python gpu编程_Python笔记_第四篇_高阶编程_进程、线程、协程_5.GPU加速

    Numba:高性能计算的高生产率 在这篇文章中,笔者将向你介绍一个来自Anaconda的Python编译器Numba,它可以在CUDA-capable GPU或多核cpu上编译Python代码.Pyt ...

  9. Python笔记_第四篇_高阶编程_进程、线程、协程_5.GPU加速

    Numba:高性能计算的高生产率 在这篇文章中,笔者将向你介绍一个来自Anaconda的Python编译器Numba,它可以在CUDA-capable GPU或多核cpu上编译Python代码.Pyt ...

最新文章

  1. 一个高端大气上档次的壁纸网站,突破你的的审美
  2. linux看门狗设备,基于Linux构建无人值守系统(看门狗)
  3. ai人工智能在手机的应用_强化学习在人工智能中的应用
  4. 删库跑路事件发生,SaaS云服务如何守护数据安全
  5. 客户关系管理系统-帮管客CRM客户管理系统 v3.0.1
  6. 《Spring攻略(第2版)》——1.5 指定Bean引用
  7. 【Tyvj3500】【BZOJ1031】字符加密,后缀数组
  8. 【英语学习】【Level 08】U02 Movie Time L6 Blockbuster
  9. 罗永浩“交个朋友”称供货方蓄意欺诈 将三倍赔偿并致歉消费者
  10. idea编辑区光标问题
  11. linux shell学习问题部分记录
  12. SQLServer中的系统表,存储过程和函数的功能及应用
  13. phpcms V9.6.0版本整合百度ueditor1.4.3.2,包括水图片上传水印
  14. 一文完成vosviewer共现网络,使用知网及web of science导出文献
  15. 《Web应用基础》课程结业报告
  16. 天猫达尔文商品管理体系通俗简介
  17. 计算机网络知识点总结(一)-----蜂窝移动网络
  18. 《天才在左、疯子在右》随笔
  19. 图解AUTOSAR(六)——服务层(Service Layer)、复杂驱动(Complex Drivers)
  20. 密码的修改(首先获取该用户的id,原密码判断是否一致,新密码和再次输入密码判断是否一样)...

热门文章

  1. IPFS网络是如何运行的(p2p网络)
  2. SPV、SPV节点和SPV钱包
  3. Android短信发送流程之多收件人发送(原)
  4. JZOJ 3600. 【CQOI2014】通配符匹配
  5. dede问答模块 那个php文件相对重要,DEDE问答(ask)模块游客匿名提问和解答
  6. Qt 多线程TCP服务端一键关闭所有客户端
  7. cpu缓冲区大小怎么设置_JAVA高薪面试必备知识点Volatile底层原理探究CPU在作怪
  8. mysql linux 客户端_MySQL—Linux查看客户端连接信息(连接数、进程等)
  9. python增量爬虫_python爬虫Scrapy框架之增量式爬虫
  10. 重装系统后不重装matlab的解决办法