文章目录
1.变量的作用域
变量起作用的范围成为变量的作用域,分为全局变量, 局部变量
1. 全局变量:
- 在函数和类定义之外声明的变量. 作用域为定义的模块,从定义位置开始知道模块结束
- 全局变量降低了函数的通用性和可读性,尽量避免
- 全局变量一般做常量使用
- 函数内想改变全局变量用global声明一下
2. 局部变量
- 在函数体重声明的变量(包括形式参数)
- 局部变量较全局变量,优先考虑使用
- 如果同名,在函数体内隐藏全局变量,只使用局部变量
# 打印全局变量a的值
a = 100
def f1():
print(a) # --打印全局变量a的值
f1()
# 优先打印局部变量的值
a = 100
def f1():
a = 300
print(a) # --打印局部变量a的值
f1()
# 改变全局变量的值
a = 100
def f1():
global a
a = 300
f1()
print(a) # --在函数内改变全局变量的值
# 打印输出局部 全局变量
a = 100
def f1():
b = 20
global a
a = 300
print(locals()) # --打印局部变量
print(globals()) # --打印全局变量
f1()
print(a)
3. 局部连梁和全局变量效率测试
import math
import time
def f1():
start = time.time()
for i in range(10000000):
math.sqrt(300)
end = time.time()
print('耗时:{}'.format(end - start))
def f2():
b = math.sqrt # -- 设置局部变量
start = time.time()
for i in range(10000000):
b(30)
end = time.time()
print('耗时:{}'.format(end - start))
f1()
f2()
2.参数传递
函数参数传递本质上是:从实参到形参的赋值操作,python中一切是"引用的赋值",python不是'值传递'
1.对"可变对象"进行写操作,直接用于原对象本身
2.对不可变对象进行写操作,会产生一个新的对象空间,并用新的值填充这块空间
- 可变对象:列表 字典 集合 自定义对象
- 不可变对象:字符串 数字 元组 function等
1. 传递可变对象引用
实际传递还是对象的引用,在函数中不创建新的对象拷贝,而是可以直接修改传递的对象
# 地址一直没有变化
a = [10, 11]
print(id(a))
def f1(m):
print(m, id(m))
m.append(12)
print(m, id(m))
f1(a)
print(a, id(a))
2. 传递不可变对象引用
在赋值操作时,由于不可变对象无法被修改,系统会创建一个新对象
a =100
print(id(a))
def f1(m):
print(id(m)) # -- 与a id相同
m += 20
print(id(m)) # --创建新id
f1(a)
print(id(a)) # -- 与a id相同,函数内部变化不影响外部
3.浅拷贝和深拷贝
内置函数copy()浅拷贝 deepcopy()深拷贝
1.浅拷贝copy()
- 不拷贝子对象的内容,只拷贝子对象的引用
IN:
import copy
a = [10, 20, [5, 6]]
b = copy.copy(a)
b.append(30)
b[2].append(7)
print(a, b, sep='\n')
OUT:
[10, 20, [5, 6, 7]]
[10, 20, [5, 6, 7], 30]
2.深拷贝deepcopy()
- 会连子对象的内存也一起拷贝,对子对象的修改不会影响原对象
IN:
import copy
a = [10, 20, [5, 6]]
b = copy.deepcopy(a)
b.append(30)
b[2].append(7)
print(a, b, sep='\n')
OUT:
[10, 20, [5, 6]]
[10, 20, [5, 6, 7], 30]
3.用 ‘=’ 进行赋值
IN:
a = [10, 20, [5, 6]]
c = a
c.append(30)
c[2].append(7)
print(c)
print(a)
OUT:
[10, 20, [5, 6, 7], 30]
[10, 20, [5, 6, 7], 30]
4. 传递不可变对象浅拷贝
a = (10, 20, [5, 6])
print(id(a))
def f1(m):
print(id(m))
m[2][0] = 666
print(m, id(m)) # -- m的id并没有变化
f1(a)
4. 参数种类及用法
函数调用时,参数默认是按照顺序传导,需要个数和形参匹配
1. 位置参数
def f1(a, b, c): # --形参名字一样会报错
print(a, b, c)
f1(2, 3, 4) # --个数不一致会报错
2. 默认值参数
def f1(a, b, c=10):
print(a, b, c)
f1(2, 3)
f1(2, 3, 4) # --给c赋值为4
3. 命名参数
def f1(a, b, c):
print(a, b, c)
f1(a=2, c=3, b=4) # --直接给形参命名
4. 可变参数
- 可变参数是指’可变数量的参数’,分为两种:
- ‘一个星号’,将多个参数收集到一个元组中
- ‘两个星号’,将多个参数收集到一个字典中
IN:
def f1(a, b, *c):
print(a, b, c)
f1(1, 2, 3, 4, 5)
OUT:
1 2 (3, 4, 5)
IN:
def f1(a, b, **c):
print(a, b, c)
f1(1, 2, name = 'zs', age = 18 )
OUT:
1 2 {'name': 'zs', 'age': 18}
5. 强制命名参数
def f1(*a, b, c): #-- *a放前面,则b c需要强制命名
print(a, b, c)
f1(3, 4 , b=1, c=2)
5. lambda函数
- lambda可以用来声明匿名函数
- lambda表达式只允许包含一个表达式,不能包含复杂语句,该表达式的计算结果就是返回值
# 一个lambda
f = lambda a, b, c, d: a * b * c * d
print(f(1, 2, 3, 4))
# 可以多个lambda同时使用
g = [lambda a: a*2, lambda b: b*2]
print(g[1](3), g[0](4))
# 函数也是对象,可以调用
f = lambda a, b, c, d: a * b * c * d
g = [lambda a: a*2, lambda b: b*2]
h = [f, g]
print(h[1][0](3))
6. eval()函数
- 将字符创当成有效的表达式来求值并计算结果
- 一般用在从别的平台直接传来的字符串需要计算
s = "print('abcdef')"
eval(s)
7. 递归函数
- 自己调用自己的函数,常用在数学归纳法
- 终止条件:表示递归什么时候结束
- 递归步骤:把第n步的值与第n-1相关联
# 求5的阶乘
def f1(n):
if n == 1:
return 1
else:
return n*f1(n-1)
result = f1(5)
print(result)
8. 嵌套函数(内部函数)
- 在函数内部定义的函数
- 封装 数据隐藏
- 贯彻DRY原则
- 闭包
def printNmae(isChinese, name, familyName):
def inner_print(a, b):
print('{0} {1}'.format(a, b))
if isChinese:
inner_print(familyName, name)
else:
inner_print(name,familyName)
printNmae(True, '小七', '高')
printNmae(False, '小八', '低')
9. nonlocal global关键字用法
a = 100
def outer():
b = 10
def inner():
nonlocal b # 声称外部函数的局部变量
print('inner b:',b)
b = 20
global a
a = 1000
inner()
print('outer b:', b)
outer()
print('a:', a)
10. LEGB规则
- python在查找变量时,是按照LEGB规则查找的
- local→enclosed(嵌套函数)→global→build in
print(str(30))
str 'global str'
def outer():
str = 'outer'
def inner():
str = 'inner'
print(str)
inner()
outer()
个人心得,仅供参考