day11笔记

一、装饰器

#1.带有参数的装饰器
def getAge1(age):
 print(age)

def outter1(func):
 def inner1(n):

     if n < 0:
         n = abs(n)

     func(n)

 return inner1

f1 = outter1(getAge1)   #func = getAge
f1(-5)   #f1---》inner

print("=" * 30)

#2.使用  @xxx 简化装饰器的使用过程,xxx表示装饰器的名称【外部函数的函数名】
#注意:只需要将@xxx添加在需要被装饰的函数的前面
def outter2(func):
 print("11111111")
 def inner2(n):
     print("2222222")
     if n < 0:
         n = abs(n)
     func(n)

 print("33333333")
 return inner2

@outter2    #相当于调用了装饰器的外部函数
def getAge2(age):
 print("4444444")
 print(age)

"""
@outter2的工作原理:
 调用outter2,并将原函数传参:getAge2 ----》func
 将装饰器内部函数返回,并getAge2的指向发生了改变,getAge2 ---->inner2
 
 getAge2  = outter2(getAge2)
"""

getAge2(-17)

#练习
def check_time(action):
 def do_action(x,y):
     #新功能
     print("十点了")
     #调用原函数
     action(x,y)

 return  do_action

@check_time   #调用外部函数,完成了传参和返回值
def go_to_bed(a,b):
 print("{}去{}睡觉".format(a,b))

go_to_bed("张三","卧室")


#3.带有返回值的装饰器
#注意:不管是闭包还是一个装饰器,任意函数和中的参数或者返回值和普通函数的用法完全相同
def wrapper(fun):
 def inner():
     print("new~~~")
     fun()

     return "aaaaaaaa"
 return inner

@wrapper
def test():
 print("test~~~~")

result = test()
print(result)

print("=" * 30)

#4.同一个装饰器修饰不同的函数
#注意:如果需要同一个装饰器给不同的函数增加相同的功能,
# 为了满足不同函数的需求,尽量将装饰器内部函数的参数设置为不定长参数,格式:*args,**kwargs
#说明:*args,**kwargs中的args和kwargs可以是任意的变量
def wrapper1(func):
 def inner1(*args,**kwargs):
     print("11111")
     func(*args,**kwargs)

 return inner1

@wrapper1
def check1():
 print("check~~~1111")

@wrapper1
def check2(a,b):
 print("check~~~2222",a,b)

@wrapper1
def check3(name,age,hobby):
 print("check~~~3333",name,age,hobby)

check1()
check2(34,10)
check3("jack",10,"唱歌")

二、生成器、可迭代对象和迭代器

1.生成器

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

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

定义生成器的两种方式
​ 第一种:列表推导式的中括号改为小括号,就是一个生成器

​ 第二种:通过函数和yield关键字生成

#1.列表推导式[]--->()
l1 = [i * 2 for i in range(5)]
print(l1,type(l1))  #<class 'list'>

g = (i * 2 for i in range(5))
print(g,type(g))
#<generator object <genexpr> at 0x10ed609a8> <class 'generator'>g

#注意:生成器也是一种容器,可以通过for循环获取其中的元素,还可以使用 next()获取生成器中的下一个元素
#Iterable:可迭代对象     Iterator:迭代器
#print(next(l1))  #TypeError: 'list' object is not an iterator
print(next(g))
print(next(g))
print(next(g))
print(next(g))
print(next(g))

#注意:如果一个生成器中的元素已经获取完毕,那么继续使用next则会报错StopIteration
#print(next(g))   #StopIteration停止迭代

print("=" * 10)

#2.函数结合yield实现
def test1():
 for x in range(5):
     print(x)
t1 = test1()
print(t1)

print("=" * 10)

#注意1:如果在一个函数的内部使用了yield关键字,那么该函数将是一个生成器
def test2():
 for x in range(5):
     print("hello",x)
     yield x * 2
     print("循环内部:",x)
t2 = test2()
print("2222",t2)

print(next(t2))   #0
print(next(t2))   #循环内部: 0   2
print(next(t2))
print(next(t2))
print(next(t2))

#print(next(t2))

"""
注意:
 a.在函数中,yield xxx, xxx表示生成器中的元素,yield在函数中出现几次,
   则意味着生成器中的元素有几个
 b.yield的作用:
     保存当前的运行状态,然后暂停执行
     将yield之后的数据作为返回值返回
 c.可以使用next()让生成器从暂停的位置开始继续执行,唤醒生成器【函数】
"""

print("=" * 30)

#练习
def show(n):
 yield n ** 3

result = show(4)
print(result)

print("元素:",next(result))
2.可迭代对象【Iterable】和迭代器
"""
【面试题】
区别
 可迭代对象:只能使用for循环遍历的对象
     a.一类是集合数据类型:如list,tuple,str,dict,set
     b.generator:()和函数

 迭代器:不但可以使用for循环遍历,还可以使用next函数获取元素的对象
     目前只有生成器
联系:
 如果一个数据是可迭代对象,不一定是迭代器
 如果是迭代器,则一定是可迭代对象
 可以通过iter()将不是迭代器的可迭代对象转化为迭代器
"""

from collections import  Iterable,Iterator

#isinstance(数据,类型),判断指定数据是否是指定的类型

print(isinstance([],Iterable))
print(isinstance({},Iterable))
print(isinstance((x for x in range(5)),Iterable))

print("**********")

print(isinstance([],Iterator))
print(isinstance({},Iterator))
print(isinstance((x for x in range(5)),Iterator))


print(isinstance(iter([]),Iterator))
print(isinstance(iter({}),Iterator))

三、函数递归

递归函数:一个会调用自身的函数被称为递归函数

递归调用:一个函数,调用自身,称为递归调用

递归包含了一种隐式的循环,它会重复执行某段,但这种重复无须循环控制【凡是循环能干的事,递归都能搞定】

使用递归解决问题的思路使用递归解决问题思路:

​ a.找到一个临界条件【临界值】

​ b.找到相邻两次循环之间的关系

​ c.一般情况下,会找到一个规律【公式】

#1.函数自己调用自己,称为递归
# def test():
#     print("hello")
#     test()
#
# test()
#RecursionError: maximum recursion depth exceeded while calling a Python object

#2.需求1:封装一个函数,传入一个数,返回对应的数,如:10---》55,7---》13
"""
斐波那契数列

1  2  3   4    5    6    7     8    9    10   11
1  1  2   3    5    8   13    21   34    55   89.。。。


分析:fun(n)
fun(1) --->1
fun(2) ---->1
fun(3)--->fun(2) + fun(1)
fun(4)--->fun(3) + fun(2)
....
fun(10)---->fun(9) + fun(8)

...
fun(n)---->fun(n - 1) + fun(n - 2)

"""
count = 0

def fun(n):
 #统计函数执行的次数
 global  count
 count += 1
 if n == 1 or n == 2:
     return 1
 else:
     return fun(n - 1) + fun(n - 2)

print(fun(10))   #10--->55
# print(fun(1))    #1
# print(fun(2))    #1

print(count)

#3.需求2:用函数递归的思想求1~某个数之间所有整数的和
"""
getsum(1)---->1
getsum(2)--->getsum(1) + 2
getsum(3) ---->getsum(2) + 3
.....
getsum(50)---->getsum(49) + 50
...
getsum(n)---->getsum(n - 1) + n
"""
def getsum(n):
 if n == 1:
     return 1
 else:
     return getsum(n - 1) + n

print(getsum(100))  #5050

四、包和模块

1.包

包是一种管理 Python 模块命名空间的形式,采用"点模块名称"

就好像使用模块的时候,你不用担心不同模块之间的全局变量相互影响一样,采用点模块名称这种形式也不用担心不同库之间的模块重名的情况

Python package本质是一个文件夹【目录】,但是特殊之处在于在改目录下有一个文件,名为__init__.py,代表初始化,前期其中不写任何内容,后期会在其中书写项目的配置信息

注意:一个py文件实际上就是一个模块
2.模块
2.1自定义模块
#一、import  xxx
#说明:xxx表示需要被导入的模块的路径,语法:点语法【模块的层级关系】,import表示将指定的文件加载

#1.import  xxx,缺点在于:当模块的层级关闭比较复杂时,则调用函数比较麻烦
#注意:路径使用的是相对路径,默认参照的路径是当前工程的根目录
# import  aaa.test
# import  bbb.test

# aaa.test.func()
# bbb.test.func()


#2.as可以给比较复杂的路径起一个别名,然后通过别名调用函数
import  aaa.test  as a
import  bbb.test  as b

a.func()
b.func()

#注意:通过import xxx方式导入模块,调用函数默认从当前文件查找
def func():
 print("ccccc")
func()

def func():
 print("ccccc~~~~22222")
func()
#二、from  xxx1 import xxx2
#说明:xxx表示模块的路径,xxx2表示需要导入的内容【变量,函数,类】


#1.注意:from  xxx1 import xxx2,可以简化函数的调用,将不再指明函数的来源,
# 但是缺点:当不同模块中出现同名的函数,后导入的模块中的函数会覆盖先导入的
"""
from bbb.test import func1,func2
from aaa.test import func1,func2

func1()
func2()

def func1():
 print("当前文件")
func1()
"""

#2.from  xxx1 import *,*代表所有
from aaa.test import *

func1()
func2()

"""
建议from ...import 
"""
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值