In python, functions are first-class objects, and functions are first-class citizens
本质上函数可以当变量用
def func(): # func=函数的内存地址
print("from func")
1.可以赋值
f = func
print(f) #打印的结果就是func的内存地址
f() #运行代码func(),from func
2.可以当作参数传给另一个函数
def foo(x):
print(x)
x() #加括号触发func代码的运行,from func
func=内存地址
foo(func)
3.可以当作函数的返回值
def foo(x):
return x
res=foo(func)
print(res)
4.可以当作容器类型的元素
l=[func]
l[0]() #把func函数名当作元素放进l的列表中.运行代码结果为from func
银行取款功能
def withdraw():
print("提款")
def tranfer():
print("转账")
def check_balance():
print("查询余额")
def save():
print("存款")
func_dic = {
"1": ["提款", withdraw],
"2": ["转账", tranfer],
"3": ["查询余额", check_balance],
"4": ["存款", save]
}
while True:
print("0" "退出")
for k,v in func_dic.items():
print(k)
choice = input("输入指令").strip()
if choice == "0":
break
if choice in func_dic:
func_dic[choice][1]()
else:
print("输入错误")
Nested function call
def max2(x,y):
if x>y:
return x
else:
return y
def max4(a, b, c, d):
res1 = max2(a, b)
res2 = max2(res1, c)
res3 = max2(res2, d)
return res3
print(max4(11, 99, 66, 55)) #打印结果为99
Nested definition of functions
def f1():
x = 10
def f2():
print("from f2")
print(x) #一个变量放进函数里面只能在函数里面使用
print(f2)
f1()
print(x) #打印结果不显示
print(f2) #打印结果不显示
namespaces: The place where the
name is stored. Built-in namespace: The built-in name is stored.
Life cycle: generated when the python interpreter is started, and destroyed when it is closed
全局名称空间:存放的是顶级的名字(只有不在函数内的都是顶级名字)
生命周期:运行python文件时则产生,python文件运行完毕则销毁
运行python,启动python解释器,先运行内置名称空间文件,然后会立刻运行全局名称空间文件,再是局部空间
x = 10
y = 20
if 1 > 0:
z = 30
with open("a.txt", mode="wt")as f:
a = 333
while True:
c = 444
以上这些都是属于全局名称空间
局部名称空间:存放的是函数内的名字
生命周期:定义函数时是不会产生名称空间的,调用函数则产生,函数调用完毕则销毁
x=10
def foo(m):
m=111
n=222
foo(111)
内置名称空间就一个,一个文件就一个全局名称空间,调用一个函数就有一个局部空间名称,局部空间名称有好多个
名称空间找名字的优先级关系:先从当前空间找,一级一级往上找.名称空间之间没有嵌套关系
在函数内找名称,先从函数局部名称空间里找名字,再去全局名称空间找,最后再去内置名称空间找
如果在全局名称空间找,就先从全局名称空间里面找名字,再去内置空间找,不会去局部名称空间找
核心:名字的访问优先级
基于当前的位置向外查找
函数内->外层函数->...->全局->内置
在定义的时候不要把内置的名字拿来定义.这样有可能会覆盖内置的名字
len = 10
def func():
len = 20
print(len) #len在局部名称空间内,运行结果先运行len=20
func()
print(len) #len在全局名称空间内,运行结果len=10
案例
def f1():
# x=555
def f2():
# x=666
print(x)
f2()
x = 444
f1()
改代码运行时,先从局部名称空间最里层,先找到x=666,
再找到x=555,如果局部名称空间内没有找到名称时,会找到全局名称空间x=444
按照顺序找到任意一个名称都不会再继续往外层寻找了
LEGB: (It is established in the function definition stage)
L: local function internal scope
E: between Enclosing function internal and embedded function
G: Global global scope
B: build-in built-in function
名称空间与作用域的关系时在函数定义阶段(扫描语法时)就确立的,与什么时候调用以及调用位置无关
案例1:
x=111
def f1():
print(x)
def f2():
x = 222
f1()
f2() 在定义阶段,x=111,结果为111
案例2:
x = 111
def f1():
print(x)
x = 222 #局部名称空间的x是先引用后定义的,运行代码会直接语法报错
f1()
Scope
Global scope: built-in name space + global name space
Features: global survival, global effective
Local scope: local name space name
Features: temporary inventory, local effective
Global
case 1 When the name of the global namespace is a variable type
l = []
def func():
l.append(1111)
func()
print(l)
Case 2 When the global space name is an immutable type
x = 111
def func():
global #当全局的值是不可变类型时,加了global全局作用域后会把全局的x=111的值改成函数里面x=222的值
x = 222
func()
print(x)
尽量不要用global局部作用域改全局的作用域
nonlocal
x = 111
def f1():
x = 222
def f2():
nonlocal x # 声明函数名是来自外层函数的,不是全局。加了nonlocal打印结果为x=333
x=333
f2()
print(x)
f1()
#nonlocal会把外层的f1的x=222改成内层的x=333,如果说第一个外层没有找到局部名会一直往外层找,找到全局层之前还找不到会直接报错
Closure function:
closed: refers to the function in the function when the function is defined.
Package: it is worthwhile that the function refers to the name of an outer function scope
def outter():
x = 111
def wrapper():
print(x)
return wrapper
f = outter()
print(f)
def foo():
x=222
f()
foo()
Scheme of passing parameters for function body code
方案1:直接用参数传
def wrapper(x):
print(x)
wrapper(111)
wrapper(222)
wrapper(333)
方案2:闭包函数传参
def outter(x):
# x=111
def wrapper():
print(x)
return wrapper
f1 = outter(111)
f1()
f2 = outter(222)
f2()
f3 = outter(333)
f3()
Decorator
What is a decorator? A
decorator is a tool used to add new functions to the decorated object
Why use a decorator?
Open and closed principle: once the software is online, it should be closed to modify the source code and develop extended functions.
Principles:
1. Do not modify the source code in the
function 2. Do not modify the calling method of the function The
decorator is to follow Under the premise of principles 1 and 2, add new functions to the decorated object
How to implement the decorator
Requirement: add the function of counting the running time of the function index
方案一:
import time
def index():
start = time.time()
time.sleep(1)
print("from index")
stop = time.time()
print("run time is %s" % (stop - start))
index()
方案二:
import time
def index():
time.sleep(1)
print("from index")
start = time.time()
index()
stop = time.time()
print("run time is %s" % (stop - start))
方案三:
import time
def index():
time.sleep(1)
print("from index")
def wrapper():
start = time.time()
index()
stop = time.time()
print("run time is %s" % (stop - start))
wrapper()
方案四:
import time
def index():
time.sleep(1)
print("from index")
def wrapper(func):
start = time.time()
func()
stop = time.time()
print("run time is %s" % (stop - start))
wrapper(index)
方案五:
import time
def index():
time.sleep(1)
print("from index")
def wrapper(func):
start = time.time()
func()
stop = time.time()
print("run time is %s" % (stop - start))
wrapper(index)