day10
全局变量和局部变量
局部变量:
定义在函数内部的变量称为局部变量(函数的形参也是局部变量)
局部变量只能在函数中使用
局部变量在函数调用时才能被创建,在函数调用之后会自动销毁
全局变量:
定义在函数外部,模块内部的变量称为全局变量
全局变量所有的函数都可以直接访问(但函数内部不能将其赋值)
示例见:
global_local.py
说明:
1.局部变量只能在其被声明的函数内部访问,而全局变量可以在整个模块范围内访问
2.在函数内部赋值语句不会对全局变量造成影响
3.在局部范围内可以访问全局变量,但是在全局不能访问局部变量,因为在函数调用完毕后,局部变量销毁
4.函数名也是全局变量(fn)
def fn(c, d):
e = 300
示意:
L = []
def input_number():
L2 = []
while True:
n = int(input("请输入正整数:"))
if n < 0:
break
L2.append(n)
L = L2
input_number()
print(L)
globals()/locals()函数
globals() 返回当前全局作用域内变量的字典
locals() 返回当前局部作用域内变量的字典
示例见:
globals_locals.py
a = 1
b = 2
c = 3
def fn(c, d):
e = 300
print("locals()返回",locals())
print("globals()返回",globals())
print(c) #打印局部变量绑定的对象
print(globals()['3']) #打印全部变量绑定的对象
fn(100, 200)
函数变量:
函数名是变量,它在创建函数时绑定一个函数
示例见:
function_variable.py
def fn():
print("hello world!") #fn绑定函数
f1 = fn #f1也绑定这个函数
print(fn) #<function fn at 0x7f138e4d6f28>
print(f1) #<function f1 at 0x7f138e4d6f28>
print(f1()) #None
def f1():
print("函数f1被调用")
def f2():
print("函数f2被调用")
f1, f2 = f2, f1 #f1,f2交换绑定
f1() #f2被调用
f2() #f1被调用
一个函数可以作为另一个函数的实参传递
示例见:
function_give_function.py
def f1():
print("hello f1")
def f2():
print("hello f2")
def fx(fn):
print(fn) #<function f1 at 0x7fb921cebf28>
fn() #调用fn绑定的函数
fx(f1) #请问如何执行?#fn是函数 fn()是调用函数fn
fx(f2)
#fx(f1)就是将f1绑定的语句块交给fn绑定
看懂下面的代码在做什么:
def myinput(fn):
L = [1,3,5,7,9]
return fn(L)
print(myinput(max)) #9
print(myinput(min)) #1
print(myinput(sum)) #25
函数可以返回另一个函数:
示例见:
return_function.py
def get_function():
s = input("请输入您要做的操作:")
if s == '求最大':
return max
elif s == '求最小':
return min
elif s == '求和':
return sum
L = [2,4,6,8,10]
f = get_function() #让get_function返回给我们一个函数
print(f(L))
练习一:
写一个计算公式的解释执行器
已知有如下函数:
def myadd(x, y):
return x + y
def mysub(x, y):
return x -y
def mymul(x, y):
return x * y
def get_fun(op):
.....#自己实现
get_fun(op)函数传入字符串'加'或'+'返回myadd
get_fun(op)函数传入字符串'乘'或'*'返回mymul
在主函数中程序如下:
def main():
while True:
s = input("请输入计算公式:") #10加20
L.s.split() #L = ['10','加','20']
a = int(L[0])
b = int(L[2])
fn = get_fun(L[1])
print("结果是:",fn(a,b)) #结果是:30
#方法一:
def myadd(x, y):
return x + y
def mysub(x, y):
return x - y
def mymul(x, y):
return x * y
def get_fun(op):
if op == '加' or op == '+':
return myadd
if op in ('减', '-'):
return mysub
if op in ('乘', '*'):
return mymul
def main():
while True:
s = input("请输入计算公式:") #10 加 20
L = s.split() #L = ['10','加','20']
a = int(L[0])
b = int(L[2])
fn = get_fun(L[1])
print("结果是:",fn(a,b)) #结果是:30
main()
#方法二:
def get_fun(op):
if op == '加' or op == '+':
def myadd(x, y):
return x + y
if op in ('减', '-'):
def mysub(x, y):
return x - y
if op in ('乘', '*'):
def mymul(x, y):
return x * y
def main():
while True:
s = input("请输入计算公式:") #10 加 20
L = s.split() #L = ['10','加','20']
a = int(L[0])
b = int(L[2])
fn = get_fun(L[1])
print("结果是:",fn(a,b)) #结果是:30
main()
函数的嵌套定义:
函数嵌套定义是指一个函数里用def语句来创建另一个函数的情况
示例:
def fn_outter():
print("fn_outter()被调用")
def fn_inner():
print("fn_inner被调用")
fn_inner() #调用嵌套函数fn_inner
fn_inner() #第二次调用
print('fn_outter调用结束')
fn_outter() #调用外层函数
python3 的四个作用域
作用域也叫名字空间,是访问变量时查找变量名的范围空间
python3 的四个作用域 LEGB
作用域 英文解释 英文简写
局部作用域(函数内) local(function) L
外部嵌套函数作用域 Enclosing function locals E
函数定义所在模块作用域 Global(module) G
python内置模块的作用域 Builtin(Python) B
注:
内建函数: max min sum 等都在python内置模块的作用域,不能改变,只能读取
示例见:
namespace.py
v = 100 #函数定义所在模块作用域
def fun1():
v = 200 # 外部嵌套函数作用域
print("fun1.v=",v)
def fun2():
v = 300 #局部作用域(函数内)
print('fun2.v=',v)
fun2()
fun1()
print("全局变量v=",v)
变量名查找规则:
在访问变量时,先查找本地(局部)变量,然后是包裹此函数外部的函数内的变量,之后是全局变量,最后是内建作用域内的变量
即: L-----> E------> G----->B
在默认情况下,变量名赋值(赋值语句)会在当前作用域内创建变量和修改变量
v = 0
def fn(x):
v += x #错误,把v看做局部变量,在局部内未绑定
global语句
作用:
告诉解释执行器,global语句声明一个或多个变量,这些变量的作用域为模块级作用域,也称全局作用域
全局声明global将赋值变量映射到模块文件内部的作用域
语法:
global 变量名1, 变量名2...
示例见:
global.py
v = 100
def fn():
global v # 告诉解释执行器python3,v是全部变量,不是局部变量
v = 200
fn()
print('v=',v)
说明:
1.全局变量如果要在函数内部被赋值,则必须经过全局声明(否则
会被认为是局部变量)
2.全局变量在函数内部不经过声明就可以直接访问
示例: global2.py
v = 100
def fn():
v = 200 # 不建议在globalz之前声明局部变量
print(v)
global v #v不能既是全局又是局部变量
v = 300
print(v)
fn()
print('v=',v)
3.不能先声明局部变量,再用global声明全局变量,此做法不和规则
4.global变量列表里的变量名不能出现在函数的形参列表里
示例: global3.py
v = 100
def fx(v):
global v #此处错误,fx(v)形参中的v与全局变量中的v冲突
v = 300
fx(v)
print(v)
nonlocal语句
作用:
告诉解释执行器,nonlocal声明的变量不是局部变量,也不是全局变量,而是外部嵌套函数内的变量
语法:
nonlocal 变量名1,变量名2,...
示例见:
nonlocal.py
v = 100
def f1():
v = 200
print("f1.v=",v)
def f2():
nonlocal v
v = 300
print("f2.v=",v)
f2()
print("调用f2()后的f1.v=",v)
f1()
print("全局的v=",v)
#结果为:
# f1.v= 200
# f2.v= 300
# 调用f2()后的f1.v= 300
# 全局的v= 100
说明:
1.nonlocal 语句只能被嵌套函数的内部进行使用
def fx():
nonlocal v
v = 100
#没有嵌套不能使用
2.访问nonlocal变量进行赋值操作,将对外部嵌套函数作用域内的
变量进行操作
3.当有两层或两层以上函数嵌套时,访问nonlocal变量只是
对近一层变量进行操作
示例见nonlocal2.py
def f1():
v = 200
def f2():
v = 300
def f3():
nonlocal v #修改f2中的局部变量v
v = 400
f3()
print("f2.v",v)
f2()
print("f1.v",v)
f1()
#结果是
# f2.v 400
# f1.v 200
4.nonlocal语句的变量列表里的变量名,不能出现在此函数形参列表中
def 语句
语法:
def 变量名/函数名(形参):
语句块
lambda 表达式
作用:
创建一个匿名函数对象
同def 类似,但不提供函数名
语法:
lambda [形参名1,形参名2,....]:表达式
示例见:
lambda.py
# def myadd(x, y):
# return x + y
# 等同于
myadd = lambda x, y: x + y #创建函数
print('20 + 30 =',myadd(20, 30))
print('40 + 50 =',myadd(40, 50))
fx = lambda:print("hello world!")
fx()
# hello wprld!
语法说明:
1.lambda只是一个表达式,它用来创建一个函数
2.当lambda表达式调用时,先执行(:) 后的表达式,并返回表达式的结果的引用
3.lambda表达式创建的函数只能包含一条表达式
4.lambda比函数简单且可以随时创建和销毁,有利于减少程序的偶合度
(形参越少对外界依赖程度越小,偶合度越低的程序越好)
练习二:
1.写一个lambda表达式,创建一个函数,此函数判断参数n 的平方
加1能否被5整除,如果能整除返回True,否则返回False
fx = lambda n:...
print(fx(3)) #True
print(fx(4)) #False
fx = lambda n: True if (n ** 2 + 1) % 5 == 0 else False
# fx = lambda n:(n ** 2 + 1) % 5 == 0
print(fx(3))
print(fx(4))
2.写一个lambda表达式,返回两个形参的最大值
def mymax(x, y):
...
mymax = lambda...
print(mymax(100,200)) #200
def mymax(x, y):
if x > y:
return x
else:
return y
mymax = lambda x, y:max(x, y)
#mymax = lambda x, y:x if x > y else y
print(mymax(100,200))
看懂下面的程序在做什么?
def fx(f, x, y):
print(f(x, y))
fx((lambda a, b:a + b),100,200)
fx((lambda x, y:x ** y),3,4)
#lambda附给f
eval,exec函数
eval()函数
作用:
把一个字符当成一个表达式来执行,返回表达式执行后的结果
注:eval只能给表达式不能给语句
格式:
eval(source, globals=None, locals=None)
示例见:
eval.py
x = 100
y = 200
s = "x + y"
a = eval(s) #解释执行s字符串,把表达式的值返回回来
print(a) #300
b = eval(s,None,{'x':1,'y':2})
print(b) #3
c = eval(s,{'x':10,'y':20},{'x':1})
print(c) #21
exec()函数
作用:
把一个字符串当成一个程序来执行
格式:
exec(source, globals=None, locals=None)
示例:
s = "x=100\ny=200\nprint('x+y=',x+y)\ndel x, y"
exec(s)
课后练习:
1.给出一个数n,写一个函数myfac(n)来计算n!(n的阶乘)
n! = 1*2*3*4*5*....*n
print(myfac(5)) #120
2.给出一个数n,写一个函数计算:
1 +2**2+3**3+4**4+....+n**n的和
3.写程序打印杨辉三角(只打印六层)
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1