s = ' 害怕自己一事无成,老无所依 '
#len(s)
def my_len(): #定义函数 声明函数
i = 0
for k in s:
i += 1
print(i)
return i #返回值
length = my_len() #函数调用
print(length)
#函数定义之后,可以在任何需要它的地方调用
#len()1.不能变,只能计算s字符长度 2.只是输出了结果
#返回的重要性 返回值 1没有返回值 2返回一个值 3返回多个值
#没有返回值---返回None
#不写return
#只写return
#return None -----不常用
def func():
return{'k':'g'}
# 返回一个值
#可以返回任何数据
#只要返回了就可以接收
#如果在一个程序中有多个retunrn,那么只执行第一个
def func2():
return1,2
f= func2()
print(r)
#返回多个值
#多个返回值用多个变量接收:有多少返回值就用多少变量接收
#用一个变量接收:得到的是一个元组
def f1(l1): #1
for i in l1: #5
print(i) #6
def f2(l1): #1
f1(l1) #4
for i in l1: #7
print(i) #8
f2([1,2,3,4]) #3
#参数
#没有参数
#定义函数和调用函数时括号里都不写内容
#有一个参数
#传什么就是什么
#有多个参数
def my_sum(a,b):
res = a+b #result
return res
my_sum(1,2)
print(ret)
站着实际参的角度上:
按照位置传参
按照关键字传参
混着用可以,但是必须先按照位置传参,再按照关键字传参
不能给同一个变量传多个值
站着形参的角度上
位置参数:必须传,且有几个参数就传几个值
只有调用函数的时候
按照位置传: 直接写参数的值
按照关键字: 关键字= 值
定义函数的时候:
位置参数: 直接定义参数
默认参数, 关键字参数: 参数名 = '默认的值'
顺序: 必须先定义位置参数, 然后*args,再然后定义默认参数 最后**kwargs
def open(file, mode='r', buffering=None, encoding=None, errors=None, newline=None, closefd=Truedef classmate(name,sex='男') print('%s : %s'%(name,sex
classmate('关公','男')classmate('小梦','男')
classmate('张飞','男')
classmate('樱花妹','女')
动态参数 : 可以接受任意多个参数
参数前必须加*,习惯参数名args,
参数名之前加**,习惯参数名kwargs
*args 关键字传参不行
def print(self, *args, sep=' ', end='\n', file=None):
def sum(*args):
n = 0
for i in args:
n+=i
return(n)
print(sum(1,2,3,4,5,6))
def func(**kwargs):
print(kwargs)
func(a = 1,b = 2,c = 3)
func(a = 1,b =2)
func(a = 1)
动态参数有两种
*args: 接受的是按照位置传参的值,组织成一个元组
**kwargs: 接受的是按照关键关键字传参的值,组成一个字典
args必须在kwargs之前
def func(*args,default = 1,**kwargs):
print(args,kwargs)
func(1,2,3,4,5,default =2,a = 'aaaa',b = 'bbbb')
只要传参的时候,先位置在默认,就不会报错。全能!
动态参数的另一种传参方式
def func(*args): 站在形参的角度上,给变量加上*,就是组合左右传来的值。(*=组合)
print(args)
func(1,2,3,4,5)
l = [1,2,3,4,5)
func(1[0],[1].[2])
func(*l) 在站在实参的角度上给一个序列加上*,就是将这个序列按照顺序打散(*=打散)
def func (**kwargs):
print(keargs)
func(a=1,b=2)
d = {'a': 1, 'b' : 2} #定义一个人字典d
# func(**d)
函数的注释
def func():
pass
'''
这个函数实现了什么功能
参数1:
参数2:
:return: 是字符串或者列表的长度
'''
pass
-----------
-----------
函数
函数的定义 def
函数的调用
函数的返回值 return
函数的参数
形参
位置参数 :必须传
args : 可以接收任意多个位置参数
默认参数 :可以不传
**kwargs :可以接收多个关键字参数
实参: 按照位置传参,按照关键字传参
-----------------------------
----------------------
-----------------
复习
#函数 可用性强,复用性强
def 函数名():
函数体
return 返回值
所有的函数 只定义不调用就不执行
函数一定要先定义后调用
函数名() 不接收返回值
返回值=函数
返回值
1)没有返回值: 默认返回None
不写return :函数内的代码执行完毕自动结束
只写return:结束一个函数
return None
2)返回一个值:结束了函数且返回一个值,可以是任意的值
3)返回多个值: 多个值之间用逗号隔开,接收的时候可以用一个变量接收(元组),也可以用等量的多个变量接收
#参数
形参 def f(a): a就是形参,因为不知道后面a定义的是什么。形参:定义函数的时候
位置参数
*args 动态参数 可以接收任意多个按位置传入的参数
默认参数 可以不传
**kwargs 动态参数可以接收任意多个按关键字传入的参数
实参 ret = f('苹果') 调用函数的时候
按照位置传参数
按照关键字传参数
可以混用 位置参数必须在关键字传参之前
不能对一个参数重复赋值
--------------------------------------------
def qqxing(l = []): 如果默认参数的值是一个可变数据类型,那么每次调用函数的时候,如果不传值就公用这个数据类型的资源
lappend(l)
print(l)
qqxing() [1]
qqxing() [1]
qqxing() [1,1]
qqxing() [1,1,1]
def qqxing(k,l = {}):
l['k'] = 'v'
print(l)
------------------
--------------
函数进阶
a = 1
def func(a)
print(a)
func()
def func():
a= 1
func()
print(a)
这样不行外面定义一个变量,函数里面可以用
函数里面定义一个变量,外面不能用。
命名空间和作用域
内置命名空间:就是python解释器一启动就可以使用的名字储存在内置命名空间中
print() input() list tuple ......
内置的名字在启动解释器的时候就被加载进内存里
全局命名空间 :我么写的代码但不是函数中的代码
是在程序从上到下被执行的过程中依次加载进内存的
放置了我们设置的所有变量名和函数名
局部命名空间 ----函数
就是函数内部定义的名字
当调用函数的时候才会产生这个命名空间 随着函数执行的结束 这个命名空间就又消失了
在局部:可以使用全局、内置命名空间中的名字
在全局:可以使用内置命名空间,但是不能在局部中使用
在内置:不能使用局部和全局的名字的
def func():
a = 1 #a已经执行结束了
func()
print(a)
内置的命名空间 | |
全局的命名空间 | |
局部命名空间 |
从下往上找可以,从上往下依赖不行。依赖倒置原则
def max(1):
print('in max func')
print(max([1,2,3]))
在正常情况下,直接使用内置的名字
当我们在全局定义了和内置名字空间中同名的名字时,会使用全局的名字
当我自己有的时候 我就不找我的上级要了
如果自己没有,就找上一级要,上一级没有再找上一级 如果内置的名字空间都没有 就报错
def input(): 内置的名字:input、print
print('in input now')
def func(): 全局的名字空间
input() input func
<a = 1 def wahaha 都是在定义>
func() 局部的名字空间 func 没有,所以没找着,所以去上一级找,上一级找到了,就不再使用内置空间的名字空间了
func() 函数名加上()代表一个函数的执行
函数不加括号代表指定是这个函数所在的内存的地址
-----------------
a = 0
def outer ():
# a = 1
def inner ():
# a = 2
def inner2():
# a = 3 这里如果是nonlocal a 那么inner下没有 a 就会再往上找,out如果有a就在out中找,不影响全局。两者都没就报错
print(a) 在内部函数使用变得时候,是从小局部到全局到内置名字的过程
一级一级往上找, 找到最近的一个就使用————作用域链
inner2()
inner()
outer()
nonlocal 只能用于局部变量 找上层中离当前函数最近一层的局部变量
声明了nonlocal的内部函数的变量修改会影响到 离当前函数最近一层的局部变量
对全局无效
对局部也只是对最近的一层有影响
函数名 本质上就是指向内存地址的一个名字
def func():
print(123)
func() 函数名就是内存地址
func2 = func #函数名可以赋值
func2()
l = [ func, func2] #函数名可以作为容器类型的元素
print(l)
for i in l:
i()
def wahaha(f):
f()
return f #函数名可以作为函数的返回值
qqxing = wahha(func) #函数名可以作为函数的参数
qqxing 此时也是指向func函数,f func qqxing本质上都是指向函数地址
第一类对象(furst-class object)指
1,可以运行期创建
2,可以作为函数参数或返回值
3,可存入变量的实体
函数名就是第一类对象
不明白?就当普通变量用
-----------------------------------
----------------------
闭包:只要是闭包一定是嵌套函数,内部函数调用外部函数的变量
def outer():
a = 1 如果在这个地方没有a 那么这只是一个嵌套函数而已,不是闭包
def inner():
print(a)
print(inner.__closure__)
outer()
打印显示 cell at 就是闭包
def outer():
a = 1
def inner():...
inner() 这不是常见使用闭包的方法,常用的是return inner()
outer()
#意思就是 内部def 创建一个函数inner,把这个函数以返回值得形式返回给outer()这个值
每次调用outer 就产生一个命名空间,这个命名空间创建a,inner
---------------------------------------
-------------------
闭包的应用
模块 import urllib 相当于一个python 叫urllib的文件
from urllib.request import
from urllib.request import urlopen
ret = urlopen('http://www.xiaohua100.cn/index.html').read()
print(ret)
def get_url():
ret = urlopen('http://www.xiaohua100.cn/index.html').read() 拿到源码信息,这个网站的源码
print(ret)
return get
get_url()
def get_url():
url = 'http://www.xiaohua100.cn/index.html' url 是外部的变量
def get(): #get 是内部函数
ret = utlopen(url).read()
print(ret) 这就是一个闭包 定义了一个get 函数 返回了get函数
return get
get_func = get_url() 以后要是想要执行
get_func()
现在这个get函数节省了资源,实现的效果就是get到url的源码显示出来。
用python取可以分析里面的数据
默写一下内容:
-------------------------------------------------------------
---------------------------------------------
-----------------------------
装饰器
#
#
装饰器形成的过程 : 最简单的装饰器 有返回值的,有一个参数的,有万能参数的
装饰器的作用 -- 不想修改函数的调用方式 但是还想再原来的函数前后添加功能
原则:开房封闭原则
装饰器的固定模式
os和操作系统交互的内置模块
#语法糖 @装饰器函数名 #被装饰的函数名
time.time print(time.time()) 从1970到现在过了多少秒
time.sleep(2) 让程序在执行到这个位置的时候停一会儿
print(time.time) #获取当前时间
def func():
start = time.time()
print('hello everyboby')
end =time.time()
return end-start
func()
import time
def func():
start = time.time()
print('hello everyboby')
time.sleep(0.001)
end = time.time()
print(end-start)
func()
----------------
def timmer(f): 计算函数的执行时间
start = time.time()
f() 记录两次时间中间的函数执行点
end = time.time()
print(end-start)
def func(): 为了让这个函数的功能独立出来,所以又在上面专门写了一个函数做计算。
time.sleep(0.01)
print('hello everyboby')
或者
def func():
time.sleep(0.01)
print('hello everyboby')
def timmer(): timmer 其实就是内存地址
start = time.time()
func()
end = time.time()
print(end-start)
timmer() # timmer(func) timmer(wasabi) 等等,里面传什么就是调用什么时间
----
def func():
time.sleep(0.01)
print('hello everyboby')
def tmmer(func): 外部函数 外部传过来的func 即使是参数也是timmer函数里,所以是个闭包
def inner(): 内部函数
start = time.time()
func()
end = time.time()
print(end -start)
return inner 这里不加()
func = timmer
func()
#不想修改函数的调用方式 但是还想在原来的函数前后添加功能
#timmer就是一个装饰器函数,只是对一个函数有一些装饰作用
#原则: 开放封闭原则
开放:对扩展是开放的
封闭:对修改是封闭的
不能轻易修改已经写好的代码。不轻易重构。
封版
def outer():
def inner():
return 'inner'
inner()
outer()
outer 返回None
装饰器的固定模式:
def wrapper(f): # timmer/login 需要什么函数就用什么 warpper就是装饰器的专用名词
def inner(*args, **kwargs):
“在被装饰之前要做的事”
ret = f(*args,**kwargs) 被装饰的函数
“在被装饰函数之后要做的事”
return ret return之后函数寄不执行了
return inner 上面定义什么 这里就return 什么 而且不加括号的。
-----------------------
第一步
def wraper():
def inner():
return inner
第二步
def wrapper(func): 下面报错因为这里没有对应的函数,所以要加补
def inner():
func() 传进一个函数,但是报错,因为上面没有函数
return inner
第三步
def wrapper(func): func = qqxing
def inner(*args,**kwargs): 最后在外面还需要传参
ret=func(*args, **kwargs) 被装饰的函数需要参数和返回值(ret) <这是被装饰的函数>
return ret 拿到的返回值还要返回给调用的地方
return inner qqing 返回到这里的inner
第四步
@wrapper 这个是语法糖,相当于qqxing = wrapper(qqxing)
def qqxing(): 现在有一个qqxing的函数
print(123)
把上面的函数以参数的形式传给wrapper之后的返回值还叫这个名字
当再次执行qqxing的时候 实际上在执行inner
ret = qqxing() #inner
-------------------
复习装饰器进阶
def wrapper(func):
def inner(*args,**kwargs):
print('在被装饰的函数执行之前做的事')
ret =func(*args,**kwargs)
print('在被装饰的函数执行之后做得事')
return ret
return inner
@wrapper
def holiday(day):
print('全体放假%天'%day)
return'好开心'
holiday (3) 3传给day
print(ret) ret 拿到返回值啦
正常情况下,调用函数,传参数,应该会有一个返回值
原函数还是会照常执行,只不过装饰器里面可以加一些东西。
接收的时候是聚合,调用的时候是打散,装饰器只是传话的