day04函数名 闭包 迭代器 生成器(各种推导式和生成器表达式) 内置函数 装饰器 递归

一.今日内容概    1.        函数本质就是一个内存地址. 用起来和变量一模一样


2. 闭包
内层函数对外层变量的使用
1. 保护变量
2. 让一个变量常驻内存


3. 迭代器
可迭代对象: __iter__
迭代器: __iter__ __next__
from collections import Iterable, Iterator
isinstance(对象, Iterable)
isinstance(对象, Iterator)

模拟for循环:
lst = []
it = lst.__iter__()
while 1:
try:
el = it.__next__()
except StopIteration:
break
list() => for => __iter__() __next__()

4. 生成器
本质就是迭代器
1. 节省内存
2. 惰性机制
3. 只能向前

生成器函数. 包含yield
yield: 把一个函数变成生成器函数. 也可以返回结果但是函数不会终止. 分段执行一个函数
return: 结束函数的调用. 返回结果

生成器保存的是代码

send() 给上一个yield位置传值
5. 各种推导式
列表推导式 [结果 for循环 if判断]
字典推导式
集合推导式
6. 生成器表达式
(结果 for循环 if条件)
面试题(挑战一下)

7. 内置函数
exec
eval
compile
可以动态执行字符串类型的代码

匿名函数: lambda 参数: 返回值
sorted() 排序
filter() 筛选
map() 映射

callable() 判断是否可以被调用 ()

8. 装饰器
可以在不改变原来的代码的基础上给函数添加新的功能
通用装饰器
def wrapper(fn):
def inner(*args, **kwargs):
'''之前'''
ret = fn(*args, **kwargs)
'''之后'''
return ret
return inner

@wrapper
def func():
pass

func()

9. 递归
函数自己调用自己
官方网站上给的递归最大深度是1000
你测试也就是998, 997

大概的预习方向:
1. 二分法
2. 面试题
3. 模块 re, json, pickle, time, random, collections, queue

二 函数名
(一)函数名:本质就是一个变量名

1.play()中()表示是不是可以被调用,callable.

 Play本质是一个内存地址

(二)函数名的作用

1.函数赋值

2.函数可以作为参数进行传递

fn可以接受任意函数,收到的函数什么都没干,直接执行.

如果在fn()的前面和后面加入一些代码,在不改变原有模式下,加入一些必要逻辑.

3.函数名可以作为返回值,返回

a和inner是平级的,都是outer()内的局部变量.a和inner都可以返回.inner指向的也是内存地址.ret

可以实现在函数外边拿到了内部的函数,实现了对内部函数的调用.

def outer():
    def inner():
        print("我是内置函数")
    print("我是外置函数")
    a=123
    return a,inner()
ret=outer()#我是外置函数   我是内置函数
print(ret)#(123, None)#因为inner()没有return,所以返回值是none

4.函数名可以作为集合类的元素

例:这两种写法有什么区别?

def f1():
    print("今天吃了1个包子")
def f2():
    print("今天吃了2个包子")
def f3():
    print("今天吃了3个包子")
def f4():
    print("今天吃了4个包子")
lst1=[f1(),f2(),f3(),f4()]
'''今天吃了1个包子
今天吃了2个包子
今天吃了3个包子
今天吃了4个包子'''
print(lst1)#因为没有return,所以全部是none[None, None, None, None]
lst2=[f1,f2,f3,f4]
print(lst2)#[<function f1 at 0x0000020095B03730>, <function f2 at 0x0000020095B037B8>, <function f3 at 0x0000020095B03840>, <function f4 at 0x0000020095B038C8>]

三 闭包

(一)含义:在内部函数中访问外层函数的变量

结果就是”哇哈哈哈”,这就是一个闭包函数.

1.好处:可以保护你的变量不受侵害.原因是这是一个局部变量,不能修改.

全局变量也是不安全,只需要一个global就可以改变

a="白蛇"
def f1():
    global a
    a="胡辣汤"
    print(a)#胡辣汤
def f2():
    print(a)#胡辣汤
f1()
f2()

 如何保护这个a,如下列代码

def f1():
    a = "白蛇"#局部变量
    def inner():
        print(a)
    return inner()
ret=f1()#白蛇

这个方式是无法改变a的.虽然a是局部变量.

2.可以让一个变量常驻内存.让内部变量常驻内存.

def outer():
    a=10
    def inner():
        return a
    return inner
ret=outer()#ret就是inner
r=ret()#调用inner()函数
print(r)#10

这样就把ret()在任意时段执行.

但是这个这个a是不能回收的,Python中为了保证inner()正常运行,a必须存在.不能倍Python回收.所有导致变量a常驻内存.

存在的问题:Python有自动垃圾回收,如下面a,b就会被回收.

3.闭包的应用:爬取一个网站.

网络请求:www.baidu.com

服务器接收后返回,然后经过浏览器处理后,呈现的现状页面.

右键:查看源代码

low版的爬虫:

首先,导入可以发送请求的一个包:

拿到网页上的源代码:

from urllib.request import urlopen
content=urlopen("https://www.renrenche.com/bj/?plog_id=b190c6142f4a8a8867f0ea8c278b2044").read().decode("utf-8")
print(content)#打印原代码

后面就是爬取数据.

比如每次想拿这个网站的内容,都需要上面的内容,需要反复请求.

具体需求:1.不能被随意改动,2.内容每次都去网络请求,很慢.

def outer():
    from urllib.request import urlopen
    content=urlopen("https://www.renrenche.com/bj/?plog_id=b190c6142f4a8a8867f0ea8c278b2044").read().decode("utf-8")
    def inner():
        return content
    return inner
print("开始爬取")
o=outer()#o就是inner,这个爬取效率很低.,
print("爬取完毕")
print("第一次爬取")
print(o())#此后的爬取就非常容易了,因为该网址变成了一个常驻内存的变量了.
print("第二次爬取")
print(o())

四 迭代器

(一)迭代和for的关系

1.可以for循环的:str\list\tuple\dict\set\range\open

2.不能循环的:int\bool

3.dir()的作用,可以查看某个数据类型可以执行那些操作.

4.可迭代的里面有__iter__;不可迭代的没有.

5.通过__iter__可以拿到内存地址.

6.iterator迭代器.

lst=["包子","","馒头","咸菜"]
it=lst.__iter__()
print(it)#<list_iterator object at 0x0000017B694D2400>
print(dir(it))#__iter__()
for i in it:
    print(i)

 迭代器本身也是可以被迭代的.

7.迭代器的核心功能__next__

 

超过了就会报错,停止迭代.

8.迭代器:老师拿着名单,对人员点名,迭代器是就是名单.他只能点第一个比如周杰伦,之后就是下一个,然后下一个.迭代器不知道后面是不是排队,只能向后面迭代,不能向前迭代.当看到stopinteraction,就停止迭代.

9.特点:不管数据类型->可以跨过数据类型的屏障,完成所有数据类型的迭代工作

所有for可以迭代的数据类型很多.也可迭代文件.可以对便利的东西进行迭代.

10.只要有__iter__()和__next__()就是迭代器.与可迭代对象不同,和迭代器没有关系,只要有__iter__()就是可迭代对象.

所以可迭代对象包括迭代器.

迭代器一定是可迭代的对象,但可迭代对象不能一定是迭代器.

11.for到底做了什么?

(1)获取迭代器

(2)获取元素

(3)处理异常.

12.如何模拟for循环(重点)

try:

except stopiteration

你去尝试,如果出事了,我兜着.但只兜着stopiteration

lst=["包子","","馒头","咸菜"]
it=lst.__iter__()
while 1:
    try:
        el=it.__iter__()
        print(el)
    except StopIteration:
        break

 五 生成器

1.生成器的特点:

(1)省内存(生成器)

(2)惰性机制:比如乡村大夫不喊下一个,下一个就不会进来,只要迭代器不执行__next__就不执行.

(3)只能下一个,不能反复.

2.迭代器拿完元素后,迭代器就失败了.需要重新拿迭代器.

lst=["今天","明天","昨天"]
it=lst.__iter__()
print(it.__next__())
print(it.__next__())
print(it.__next__())
it=lst.__iter__()#重新拿迭代器才能奏效
print(it.__next__())
print(it.__next__())

3.未来的使用中,不这么使用,用迭代器最多最多是for循环.

4.如果用官方的方法来判断XXX数据是否可迭代对象,迭代器.

iterable:可迭代的

iterator:迭代器

isinstance:判断XXX数据是否XX类型.

#True  Flase

5.generator生成器

函数中有了yield,也表示返回,就有了生成器函数.

生成器的函数运行的时候,不会执行你的函数,获取一个生成器.

生成器的执行__next__()

只能拿取一个yield

def chi():
    print("第一顿")
    yield "饺子"
    print("第二顿")
    yield "包子"

ret=chi()
print(ret)#<generator object chi at 0x0000018521321ED0>
r1=ret.__next__()#第一顿
print(r1)#饺子
r2=ret.__next__()#第二顿
print(r2)#包子

3.yield的作用:(1)把一个普通的函数变成生成器函数.(2)可以分段把一个函数去运行.(3)也可以返回结果,但函数不会终止.

4.生成器的作用:

如果数据量很大的问题,存储是一个大问题.

def order():
    lst=[]
    for i in range(1000):
        lst.append(i)
    return lst
ret=order()#数据非常大,占用较大内存
print(ret)

对上述代码进行优化:

def order():
    for i in range(1000):
        yield "学员编号",i+1
ret=order()
print(ret.__next__())#('学员编号', 1)
print(ret.__next__())#('学员编号', 2)

这样生成器,大量的节省内存.因为生成器保存的是代码,不是数据,而第一个程序保存的是数据,不是代码.

生成器几乎不占内存.

例:人一生吃20000个鸡蛋,但如果一次性买20000个不现实,可以买个鸡,想吃就让它下单。这个鸡就是生产器。

5.send()也可以像__next__一样执行生成器中的代码,都是执行到下一个yield.

send可以给上一个yield位置传值

def chi():
    print("我要吃饭了")
    yield "大米饭"
    print("我不吃主食")
    yield "锅包肉"
    print("我喜欢吃素食")
    c=yield "汉堡包"
    print(c)
    yield "吃饱"
gen=chi()
print(gen.__next__())#我要吃饭了     大米饭
print(gen.__next__())#我不吃主食     锅包肉
print(gen.__next__())#我喜欢吃素食    汉堡包
print(gen.__next__())#None   吃饱

先算=右边的yield,然后才是a,a=yield是分开执行的.

def chi():
    print("我要吃饭了")
    a=yield "大米饭"
    print(a)
    print("我不吃主食")
    b=yield "锅包肉"
    print(b)
    print("我喜欢吃素食")
    c=yield "汉堡包"
    print(c)
    yield "吃饱"
gen=chi()
print(gen.__next__())#我要吃饭了     大米饭
gen.send("大龙虾")#大龙虾 我不吃主食
print(gen.__next__())#None 我喜欢吃素食 汉堡包
print(gen.__next__())#None   吃饱

如果最后一个yield不能传值,不会再有yield,一定会报错.

这个是很少见的,应用很少.

第一个启动的时候使用__next__,不用send(),因为不能赋值.

def chi():
    print("我要吃饭了")
    a=yield "大米饭"
    print(a)
    print("我不吃主食")
    b=yield "锅包肉"
    print(b)
    print("我喜欢吃素食")
    c=yield "汉堡包"
    print(c)
    yield "吃饱"
gen=chi()
print(gen.__next__())#我要吃饭了     大米饭
gen.send("大龙虾")#大龙虾 我不吃主食
gen.send("海鲜")#海鲜 我喜欢吃素食
gen.send("火腿肠")#火腿肠 #吃饱,不执行,也就是send执行前一个yield,不执行后面的yield

五.各种推导式

1.创建一个列表,里面放10000件衣服

lst=[]
for i in range(1000):
    lst.append("学员编号:%d"%(i+1))
print(lst)
#整理成一句话
lst=["学员编号%d"%(i+1) for i in range(1000)]
print(lst)

 这就是列表推导式:[]

字典推到器:{}

集合推导式:{}

元组没有推导式 

2.列表推导式:[添加的内容 for循环 if条件]

#生成一个列表1,4,9,16,25
lst=[i**2 for i in range(1,6)]
print(lst)

3.字典推导式:{k:v for循环 if条件}

lst=["今天","明天","后天","昨天"]
dic={(i+1):lst[i] for i in range(len(lst))}
print(dic)

 4.集合推导式:{k  for循环  if条件}

字典的要求的key是可哈希的

集合就是不存value的字典,只存key

s={i for i in range(1,15,2)}
print(s)#{1, 3, 5, 7, 9, 11, 13}

5.没有元组推导式

6.生成器表达式(结果 for循环,if条件)

7.yield from:可以把列表中的数据进行返回.

六.内置函数

Python直接给你的,直接拿来用的

hash(哈希)值 数字的本身就本身,字符串的哈希也是一个数字

id()是十进制的内存地址.

help:ctrl+点,就可以看到字符串,不用percharm的时候用help

6.查看内存属性dir()

7.callable:判断你给的参数是否可以被调用.判断传进来的东能否+(),下面程序中1不能加(),会报错.

8.eval和exec 和compile:意义:可以执行动态的代码,执行字符串代码.

s="6+7+13 *6"
ret=eval(s)
print(ret)

9. 把字符串的东西还原成列表和字典

exec没有返回值.pycharm的错误不一定是错误.一般情况,pycharm的错误是错误的.

compile:编译.可以把程序预编译一部分代码.提高一部分代码的效率.

Python是一门解释性编程语言.Python的缺点就是慢,来一行解释一行.

compile(代码,文件,执行模式)

想要整体的提高运行速度,需要整体优化.

如果第一个参数给了代码,就不要给文件了,这两个部分是互斥的.

single:当程序出现交互了

不能用exal,必须用exec调用

9,复数:complex,实部+虚部

10.数学的工具,MATLAB

11.矩阵分析:numpy矩阵分析

12.二进制:bin(5) #0b101,0b表示二进制.

八进制:oct(9)#0o11

十六进制:hex(18)#0x12

print(bin(2))#0b10
print(oct(8))#0c10
print(hex(16))#0x10

 13.abs绝对值

14.pow求次幂

15.divmod

16.round

17.frozenset冻结的集合,可以把不可哈希的set可哈希.

 list对应tuple

 

18.enumerate

lst=["包子","","馒头","咸菜"]
for i in range(len(lst)):
    print(i,lst[i])
'''
0 包子
1 粥
2 馒头
3 咸菜'''
for i,el in enumerate(lst):
    print(i,el)
'''
0 包子
1 粥
2 馒头
3 咸菜'''
for i,el in enumerate(lst,100):
    print(i,el)
'''100 包子
101 粥
102 馒头
103 咸菜'''

19.all和any

all可以把等同于and,

any的作用相当于or

print(all([5,1,"haha","hehe"]))#True
print(all([5,0,"haha","hehe"]))#False
print(any([5,1,"haha","hehe"]))#True
print(any([5,0,"haha","hehe"]))#True

 20.slice,切片,切片很难用

s="您好啊,我是jay"
s1=slice(1,5)
print(s[s1])#好啊,我

 主要应用在:很多字符串,按照同样的切割方式的时候可以用.

 

21.bytearry:字节数组

22.ord和chr

ord把字符放进去,可以在其位置告诉你.

chr在计算机编码位置给,可以找到这个字

23,asci#判断你的文字是不是ASCII的范畴.

24.repr:cPython,我们写的字符串最终转换成C里面的字符串.

把字符串还原回最应该显示的样子,Python是比较随意的,通过repr可以还原成c语言.

25.r””:原样输出,和repr没有关系.

在正则表达式中会应用到.

26.format():格式化.

 

 

(3)科学计数法

lst=["包子","","馒头","咸菜"]
lst1=["今天","明天","后天","昨天"]
lst2=[1,2,3,4]
z=zip(lst,lst1,lst2)
print(z)#<zip object at 0x0000019563DCFBC8>
for el in z:
    print(el)

27.zip拉

水桶效应,最短的能合上,最长的用不上.

28.匿名函数lambda x,y:x+y

fn=lambda x,y:x+y
ret=fn(2,3)
print(ret)
def cal(x,y):
    return x+y
ret=cal(2,3)
print(ret)

一行代码搞定一个函数

语法:lambda 参数:返回值

29.sorted:排序,是正序,加上reverse就是倒叙.

lst=[5,9,15,64,85,34,25,126,445,61]
lst1=sorted(lst)
print(lst1)#[5, 9, 15, 25, 34, 61, 64, 85, 126, 445]
lst2=sorted(lst,reverse=True)
print(lst2)#[445, 126, 85, 64, 61, 34, 25, 15, 9, 5]

30.sorted可以给出自己的排序规则

比如:按照名字的长短排序:

sorted有三个函数(iter,key,reverse) #key必须是一个函数.函数会把前面每一项进行迭代.

排序规则:内部会自动的迭代前面的那个数字,迭代出来的每一项后给后面的key,并调用这个函数.然后根据函数返回的数据进行排序.

lst=["牛栏山","牛儿","门杰雷夫","kenments","勇士"]

#根据名字的长度排序
def fn(x):#x就是列表的每一项 return len(x) lst1=sorted(lst,key=fn,reverse=True)#key 必须是一个函数 #把可迭代对象迭代出来传递给函数key,根据函数的执行结果进行排序. print(lst1)

例如:根据给的年龄进行排序

lst = [{"name":"alex", "age":34, "hobby":"吹牛"},
       {"name": "wusir", "age": 14, "hobby": "吹牛牛"},
       {"name": "taibai", "age": 31, "hobby": "吹牛牛牛"},
       {"name": "taihei", "age": 12, "hobby": "吹牛牛牛牛"},
       {"name": "tailv", "age": 48, "hobby": "吹牛牛牛牛牛"},]
#根据年龄排序:
def func(dic):
    return dic["age"]
print(sorted(lst,key=lambda dic:dic["age"]))
#[{'name': 'taihei', 'age': 12, 'hobby': '吹牛牛牛牛'},\
 {'name': 'wusir', 'age': 14, 'hobby': '吹牛牛'}, \
{'name': 'taibai', 'age': 31, 'hobby': '吹牛牛牛'}, \
{'name': 'alex', 'age': 34, 'hobby': '吹牛'},\
 {'name': 'tailv', 'age': 48, 'hobby': '吹牛牛牛牛牛'}]

#按照"牛"个数排序
def fn(dic):
    return len(dic["habyy"])
print(sorted(lst,key=lambda dic:len(dic["hobby"])))
print(sorted(lst,key=lambda dic:dic["hobby"].count("牛")))
#[{'name': 'alex', 'age': 34, 'hobby': '吹牛'}, \ {'name': 'wusir', 'age': 14, 'hobby': '吹牛牛'},\ {'name': 'taibai', 'age': 31, 'hobby': '吹牛牛牛'},\ {'name': 'taihei', 'age': 12, 'hobby': '吹牛牛牛牛'},\ {'name': 'tailv', 'age': 48, 'hobby': '吹牛牛牛牛牛'}]

lambda主要应用在这里.

按照”牛”的多少排序:

30.筛选:filter

把可迭代对象,进行迭代,把每一项数据传递给前面,根据函数返回的ture和false来决定改元素,是否保留.

31.映射函数map():把可跌对象中每一项,传递给前面的函数,把函数执行的结果作为整个运算的结果.

lst=[5,9,15,64,85,34,25,126,445,61]
ret=map(lambda x:x**2,lst)
# lst1=[i for i in ret]
# print(lst1)#[25, 81, 225, 4096, 7225, 1156, 625, 15876, 198025, 3721]
lst2=[]
for i in ret:
    lst2.append(i)
print(lst2)#[25, 81, 225, 4096, 7225, 1156, 625, 15876, 198025, 3721]

主要应用:把每一个ip地址进行相同操作.

32,reduce和map相反,处理大量数据的核心思想.

33.hadoop:大数据

七.装饰器

1.开闭原则

开:对增加功能开放

闭:对修改源代码封闭,对已经写好的代码不能修改,防止今天修改,明天修改,把修改的代码变的面目全非.

例如:

反复修改一段代码是比较忌讳的.比如不同的人修改代码,就乱套了,代码是走不远的.

2.装饰器:就是在不改变源代码的基础上,给代码添加新功能.

 女娲开始造人是zaoren()

但是三年大旱,需要加入浇水water()需要加上代码

但是这也是不对的,

 

现在也不对,可以把ret换成zaoren

没有三年大旱:

def zaoren():
    print("女娲造人,吹口气")
zaoren()

三年大旱后:

def zaoren():
    print("女娲造人,吹口气")
zaoren()

#三年大旱
def water(fn):
    def inner():
        print("浇水")
        fn()
    return inner
zaoren=water(zaoren)
zaoren()

这样已经使用zaoren()程序的又可以继续zaoren()了,没有改变.

这就是装饰器的作用,这是装饰器的雏形.

3.装饰器的基本雏形

fn就是目标函数,需要装饰的函数

inner局势装饰之后的效果.

返回inner:就是方便别人调用.

例如:第二故事:yue():在yue之前需要问问行情:

def wrapper(fn):
    def inner():
        print("Alex最近行情怎么洋?")
        fn()
        print("alex你骗我")
    return inner
def yue():
    print("约一约")
yue=wrapper(yue)
yue()
#这两种表达方式一样
@wrapper
def yue():
    print("约一约")
yue()

@wrapper等同于yue=wrapper(yue)

@wraps(fn)伪装inner,就像一个fn函数,方便后面的人解读.

from functools import wraps#导入wraps模块
def wrapper(fn):
    @wraps(fn)
    def inner():
        print("Alex最近行情怎么洋?")
        fn()
        print("alex你骗我")
    return inner

@wrapper
def yue():
    print("约一约")
yue()

装饰器最大的作用,在不改变函数源代码的基础上添加新功能.

4.万能参数

def wrapper(fn):
    def inner(*args,**kwargs):#args元祖,**kwargs对应字典
        print("哈哈哈")
        fn(*args,**kwargs)
        print("呵呵呵")
    return inner
@wrapper
def chi():
    print("嗯嗯嗯")
chi()

后面的函数可以随便使用.

def wrapper(fn):
    def inner(*args,**kwargs):#args元祖,**kwargs对应字典
        print("哈哈哈")
        fn(*args,**kwargs)
        print("呵呵呵")
    return inner
@wrapper
def chi(username,password):
    print("用%s" % username)
    print("用%s" % password)
chi("alex","jintian")

待返回值的装饰器

def wrapper(fn):
    def inner(*args,**kwargs):#args元祖,**kwargs对应字典
        print("哈哈哈")
        ret=fn(*args,**kwargs)#把接收的数据打散发出去
        print("呵呵呵")
        return ret
    return inner
@wrapper
def chi(username,password):
    print("用%s" % username)
    print("用%s" % password)
    return 10000
r=chi("alex","jintian")#调用的是inner()
print(r)

5.需要对装饰器进行升级改造

from functools import wraps
def wrapper(fn):#目标函数,被装饰的函数
    @wraps(fn)#改变inner的名字
    def inner(*args,**kwargs):#args元祖,**kwargs对应字典
        print("哈哈哈")
        ret=fn(*args,**kwargs)#把接收的数据打散发出去
        print("呵呵呵")
        return ret
    return inner
@wrapper
def func():
    pass

6.这种思想:AOP,面向切面编程,就是在好好的东西切开,然后再切开的前面和后面插入一段代码,进行装饰.python里面叫装饰器.

7.装饰器的应用:

HR的工作

在执行以下操作之前,需要登录校验.

有登录的功能:

一旦登录成功

flag=False#没登录

#应用:再执行以下操作前,需要登陆验证
flag=False#没登录
def login():
    username=input("请输入名字:")
    password=input("请输入密码:")
    if username=="alex" and password=="123":
        print("登陆成功")
        global flag#引入全局变量
        flag=True
    else:
        print("登陆失败")

加上装饰器:登录验证装饰器:

#加上装饰器,登陆验证装饰器
def login_verify_wrapper(fn):
    def inner(*args,**kwargs):
        while 1:
            if flag:
                ret=fn(*args,**kwargs)
                return ret
            else:
                login()
    return inner
@login_verify_wrapper
def add():
    pass
@login_verify_wrapper
def dele():
    pass

8.带有参数的装饰器

控制装饰内部参数的位置.

执行流程:先执行wrapper_out,然后执行@

#带有参数的装饰器
def wapper_out(flag):#装饰器的参数
    def wapper(fn):
        def inner(*args,**kwargs):
            if flag==True:
                print("alex行情怎么洋")
            ret=fn(*args,**kwargs)
            return ret
        return inner
    return wapper
@wapper_out(True)#执行流程:先执行wrapper_out(True) 返回装饰器 再和@联合起来@wapper
def yue():
    print("我要约")
yue()

9.多个装饰器装饰同一个函数

离最近的先包装,逐一包装.

九.递归

1.贪吃蛇:吃一个长一节,但吃自己无限循环.

def func():
    print("哈哈")
    func()
func()

无限开拓空间,就报错了.

不要用递归.

python的递归层数最大是1000,不能超过1000.在window最大998.在苹果中是997.

整个程序的稳定性是非常差的.

递归的第一个应用:遍历文件夹

window的文件夹就是一个树

计算机的树是相反的.

大家都约定俗成,是根节点和页节点.

如果报我的电脑砍掉,c盘就是根节点.

树形结构的便利就是递归的应用.

os.path.join(s,el)#拼接文件路径.

isdir#判断是否为文件夹

递归的入口

 

千万不能执行.

树形结构的深度递归.

数据结构.

十,商品的信息如何存最简单

eval写入文件

读取文件,使用eval 把文件中的字典和字符串还原.

 

优化后:

def wrapper(fn):
def inner():
print("Alex最近行情怎么洋?")
fn()
print("alex你骗我")
return inner
def yue():
print("约一约")
yue=wrapper(yue)
yue()
#这两种表达方式一样
@wrapper
def yue():
print("约一约")
yue()

猜你喜欢

转载自www.cnblogs.com/kenments/p/10307639.html