一、全局变量和局部变量
1、局部变量:
函数的形参也是局部变量)
局部变量只能在函数内部使用
局部变量在函数调用时才能被创建,在函数调用之后会自动销毁
2、全局变量
定义在函数外部,模块内部的变量称为全局变量
全局变量所有函数都可以直接访问(但函数内部不能将其赋值)
# 此示例示意全局变量和局部变量
a = 100 # 全局变量
b = 200 # 全局变量
def fx(c): # c是局部变量
d = 400 # d是局部变量
print(a, b, c, d)
fx(300)
print(a, b)
global_local.py
说明:
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)
globals_locals.py
三、函数变量:
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被调用
function_variable.py
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)
function_give_function1.py
# 此示例示意一个函数可以作为别一个函数的实参传入另一个函数中
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'])
function_give_function2.py
看懂下面的代码在干什么:
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))
return_function.py
练习:
写一个计算公式的解释执行器
已知有如下一些函数:
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()
方法1
# 方法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()
方法2
四、函数嵌套定义
函数嵌套定义是指一个函数里用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()
function_embed_def.py
五、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)
namespace.py
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
global1.py
# global语句
v = 100
def fn():
v = 200 # 不建议在global之前来创建局部变量
print(v)
global v
# v = 300
# print(v)
fn()
print('v=', v) # 200
global2.py
# global变量列表里的变量名不能出现在函数的形参列表里
v = 100
def fx(v):
# global v # 此处错误!!!
v = 300
fx(200)
print(v)
global3.py
# 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))
global_list.py
说明:
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)
nonlocal1.py
# 当有两层或两层以上函数嵌套时,
# 访问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()
nonlocal2.py
说明:
1.
2.
3.
4.
六、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
lambda.py
语法说明:
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
练习1.py
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
练习2.py
七、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
eval1.py
# eval函数
n = int(eval(input("请输入一个表达式")))
eval2.py
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)
exec.py
练习:
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))
练习1
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))
练习2
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))
练习3