python基础(10)——全局变量和局部变量& def & eval, exec
一、全局变量和局部变量
1、局部变量:
定义在函数内部的变量称为局部变量(函数的形参也是局部变量)
局部变量只能在函数内部使用
局部变量在函数调用时才能被创建,在函数调用之后会自动销毁
2、全局变量
定义在函数外部,模块内部的变量称为全局变量
全局变量所有函数都可以直接访问(但函数内部不能将其赋值)
# 此示例示意全局变量和局部变量 a = 100 # 全局变量 b = 200 # 全局变量 def fx(c): # c是局部变量 d = 400 # d是局部变量 print(a, b, c, d) fx(300) print(a, b)
说明:
1. 局部变量只能在其被声明的函数内部访问,而全局变量可以在整个模块范围内访问
2. 在函数内部赋值语句不会对全局变量造成影响
示意:
L = []
def input_number():
L2 = []
while True:
n = int(input("请输入正整数")) # 1 2 3 4
if n < 0:
break
L2.append(n)
L = L2
input_number()
print(L)
二、globals() / locals() 函数
globals() 返回当前全局作用域内变量的字典
locals() 返回当前局部作用内变量的字典
1 # globals()/ locals()函数 2 a = 1 3 b = 2 4 c = 3 5 def fn(c, d): 6 e = 300 7 print("locals() 返回: ", locals()) 8 print("globals() 返回: ", globals()) 9 print(c) # 100 10 print(globals()['c']) # 3 11 12 fn(100, 200)
三、函数变量:
1、函数名是变量,它在创建函数时绑定一个函数
# 此示例示意函数名fn是变量.它绑定一个函数对象 def fn(): print("hello world!") f1 = fn print(fn) # <function fn at 0x7f0df513bf28> print(f1) # <function fn at 0x7f0df513bf28> print(f1()) # None def f1(): print("函数f1被调用") def f2(): print('函数f2被调用') f1, f2 = f2, f1 f1() # f2被调用 f2() # f1被调用
2、一个函数可以作为另一个函数的实参传递
1 # 此示例示意一个函数可以作为别一个函数的实参传入另一个函数中(1) 2 def f1(): 3 print("hello f1") 4 5 def f2(): 6 print('hello f2') 7 8 def fx(fn): 9 print(fn) # < function f1 at 0xXXXXXXX> 10 fn() # 调用fn绑定的函数 11 12 fx(f1) # 请问是如何执行的? 13 fx(f2)
# 此示例示意一个函数可以作为别一个函数的实参传入另一个函数中 def goodbye(L): for x in L: print("再见", x) def hello(L): for x in L: print("你好", x) def do_things(fn, L): fn(L) do_things(goodbye, ['Tom', 'Jerry', 'Spike'])
看懂下面的代码在干什么:
def myinput(fn):
L = [1, 3, 5, 7, 9]
return fn(L)
print(myinput(max)) # 9
print(myinput(min)) # 1
print(myinput(sum)) # 25
3、函数可以返回另一个函数
1 # 函数可以返回另一个函数 2 def get_function(): 3 s = input("请输入您要做的操作: ") 4 if s == '求最大': 5 return max 6 elif s == '求最小': 7 return min 8 elif s == '求和': 9 return sum 10 11 L = [2, 4, 6, 8, 10] 12 f = get_function() # 让get_function返回给我们一个函数 13 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
# 方法1 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 mymul if op in ("减", '-'): return mysub 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()
# 方法2 def get_fun(op): if op == '加' or op == '+': def myadd(x, y): return x + y return myadd if op in ('乘', '*'): def mymul(x, y): return x * y return mymul if op in ("减", '-'): def mysub(x, y): return x - y return mysub 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_nner
fn_inner() # 第二次调用
print('fn_outter() 调用结束')
fn_outter() # 调用外层函数
1 # 此示例示意函数的嵌套定义 2 def fn_outter(): 3 print("fn_outter() 被调用") 4 5 def fn_inner(): 6 print("fn_inner 被调用") 7 8 fn_inner() #调用嵌套函数 fn_nner 9 fn_inner() # 第二次调用 10 print('fn_outter() 调用结束') 11 return fn_inner 12 13 fn_outter() # 调用外层函数 14 # fn_inner() # 不可以调用 15 fx = fn_outter() 16 fx()
五、python3的四个作用域
作用域也叫名字空间,是访问变量时查找变量名的范围空间
1、python的四个作用域 LEGB
作用域 英文解释 英文简写
局部作用域(函数内) Local(function) L
外部嵌套函数作用域 Enclosing function locals E
函数定义所在模块作用域 Global(module) G
python内置模块的作用域 Builtin(Python) B
1 # python3的四个作用域 2 v = 100 # 函数定义所在模块作用域(全局) 3 def fun1(): # 外部嵌套函数作用域 4 v = 200 5 print("fun1.v=", v) 6 7 def fun2(): 8 v = 300 # 局部作用域 9 print("fun2.v=", v) 10 fun2() # 调用fun2 11 12 fun1() 13 print("全局变量v=", v)
2、变量名查找规则:
在访问变量时,先查找本地变量,然后是包裹此函数外部的函数内的变量,之后是全局变量,最后是内建作用域内的变量
即: L ---> E ---> G ----> B
在默认情况下,变量名赋值会在当前作用域内创建变量和修改变量
3、global 语句
作用:
告诉解释执行器,global语句声明的一个或多个变量,这些变量的作用域为模块级的作用域,也称作全局作用域
全局声明 global 将赋值变量映射到模块文件内部的作用域
语法:
global 变量名1, 变量名2, ...
# global语句 v = 100 def fn(): global v # 告诉解释执行器python3, v是全局变量,不是局部变量 v = 200 fn() print('v=', v) # 200
# global语句 v = 100 def fn(): v = 200 # 不建议在global之前来创建局部变量 print(v) global v # v = 300 # print(v) fn() print('v=', v) # 200
# global变量列表里的变量名不能出现在函数的形参列表里 v = 100 def fx(v): # global v # 此处错误!!! v = 300 fx(200) print(v)
# global_list L = [] print("id(L)=", id(L)) def input_number(): L2 = [] while True: n = int(input("请输入正整数: ")) # 1 2 3 4 if n < 0: break L2.append(n) # L = L2 # 创建局部变量,未改变全局变量L的绑定关系 # L.extend(L2) # 根据变量找到列表,改变的是列表而不是变量 # L += L2 # 出错 L = L + L2 return L2 input_number() print(L) # 打印什么? print('id(L)=', id(L))
说明:
1. 全局变量如果要在函数内部被赋值,则必须经过全局声明(否则会被认为是局部变量)
2. 全局变量在函数内部不经过声明就可以直接访问
3.不能先声明局部变量,再用global声明为全局变量,此做法不附合规则
4. global变量列表里的变量名不能出现在函数的形参列表里
4、nonlocal语句
作用:
告诉解释执行器,nonlocal声明的变量不是局部变量,也不是全局变量,而是外部嵌套函数内的变量
语法:
nonlocal 变量名1, 变量名2, ....
1 # nonlocal语句 2 v = 100 3 4 def f1(): 5 v = 200 6 print("f1.v=", v) 7 8 def f2(): 9 nonlocal v 10 v = 300 11 print("f2.v=", v) 12 f2() 13 print("调用f2()后的f1.v = ", v) 14 15 16 f1() 17 print("全局的v=", v)
# 当有两层或两层以上函数嵌套时, # 访问nonlocal变量只对最近一层变量进行操作 v = 100 def f1(): v = 200 def f2(): v = 300 def f3(): nonlocal v v = 400 f3() print("f2.v=", v) f2() print("f1.v = ", v) f1()
说明:
1. nonlocal 语句只能在被嵌套函数的内部进行使用
2. 对nonlocal变量进行赋值操作,将对外部嵌套函数作用域内的变量进行操作
3. 当有两层或两层以上函数嵌套时,访问nonlocal变量只对最近一层变量进行操作
4. nonlocal语句的变量列表里的变量名,不能出现在此函数形参列表中
六、def 语句
1、def语法:
def 变量/函数名(形参):
....
2、lambda 表达式
作用:
创建一个匿名函数对象
同 def 类似,但不提供函数名
语法:
lambda [形参名1, 形参名2, ...]: 表达式
# def myadd(x, y): # return x + y # 以上等同于 myadd = lambda x, y: x + y myadd = lambda x, y: x + y print('20 + 30 =', myadd(20, 30)) # 50 print('40 + 50 =', myadd(40, 50)) # 90
语法说明:
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
# 方法1 # fx = lambda n: (n ** 2 + 1) % 5 == 0 # 方法2 fx = lambda n: True if (n ** 2 + 1) % 5 == 0 else False print(fx(3)) # True print(fx(4)) # False
2. 写一个lambda表达式,返两个形参的最大值
def mymax(x, y):
...
mymax = lambda .....
print(mymax(100, 200)) # 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)
# 方法1 # def mymax(x, y): # return max(x, y) # if x > y: # return x # return y # 方法2 # mymax = lambda x, y: x if x > y else y # 方法3 mymax = lambda x, y: max(x, y) print(mymax(100, 200)) # 200
七、eval, exec 函数
1、eval() 函数
作用:
把一个字符串当成一个表达式来执行,返回表达式执行后的结果
格式:
eval(source, globals=None, locals=None)
# eval函数 x = 100 y = 200 s = "x + y" a = eval(s) # 解释执行s字符串,把表达式的值返回回来 print(a) # 300 b = eval(s, None, {'x': 1, 'y': 2}) print(b) c = eval(s, {'x': 10, 'y': 20}, {'x': 1}) print(c) # 21
# eval函数 n = int(eval(input("请输入一个表达式")))
2、exec() 函数
作用:
把一个字符串当成程序来执行
格式:
exec(source, globals=None, locals=None)
示例:
s = "x=100\ny=200\nprint('x+y=', x+y)\ndel x, y"
exec(s)
# exec函数 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*....*n
print(myfac(5)) # 120
def myfac(n): s = 1 for x in range(1,n+1): s *= x return s print(myfac(5))
2. 给出一个数n,写一个函数计算:
1 + 2**2 + 3**3 + 4**4 + .... n**n的和
def f(n): # 方法2 return sum(map(lambda x: x ** x, range(1, n + 1))) # 方法1 # s = 0 # for i in range(1, n + 1): # s += i ** i # return s print(f(3))
3. 写程序打印杨辉三角 (只打印6层)
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
# [1] # [1,1] # [1,2,1] # [1,3,3,1] # [1,4,6,4,1] # [1,5,10,10,5,1] def get_next_line(L): '''此函数将用一层的列表L 计算下一层然后返回 L = [1,3,3,1], 则返回: [1,4,6,4,1] ''' line = [1] # 最左侧的1 # 计算中间的数字 for i in range(len(L) - 1): # i绑定L的索引 line.append(L[i] + L[i + 1]) # 在最后放入一个1 line.append(1) return line def get_yh_list(n): # n 代表行数: L = [] line = [1] # 当前是第一行 for _ in range(n): L.append(line) # 当前行放进行 # 再算出下一行,准备放入 line = get_next_line(line) return L def list_to_string(L): '''此函数任意给定一个列表,将其转换为字符串 如: L = [1, 3, 3, 1], 则返回 '1 3 3 1' ''' L2 = [str(x) for x in L] # L2 = ['1', '3', '3', '1'] return ' '.join(L2) # L = [ # [1], # [1, 1], # [1, 2, 1], # [1, 3, 3, 1], # [1, 4, 6, 4, 1], # [1, 5, 10, 10, 5, 1] # ] L = get_yh_list(6) # 得到最下面一行占几个字符的宽度: max_char = len(list_to_string(L[-1])) # 居中显示 for line_list in L: s = list_to_string(line_list) print(s.center(max_char))
posted on 2018-10-12 17:25 破天荒的谎言、谈敷衍 阅读(420) 评论(0) 收藏 举报
浙公网安备 33010602011771号