作用域(scope)
作用域指的是变量生效的区域
在Python中一共有两种作用域(全局作用域和函数作用域)
b = 20 # 全局变量
def fn():
a = 10 # a定义在了函数内部,所以他的作用域就是函数内部,函数外部无法访问
print('函数内部:','a =',a)
print('函数内部:','b =',b)
fn()
print('函数外部:','a =',a)
print('函数外部:','b =',b)
全局作用域
- 全局作用域在程序执行时创建,在程序执行结束时销毁
- 所有函数以外的区域都是全局作用域
- 在全局作用域中定义的变量,都属于全局变量,全局变量可以在程序的任意位置被访问
函数作用域
- 函数作用域在函数调用时创建,在调用结束时销毁
- 函数每调用一次就会产生一个新的函数作用域
- 在函数作用域中定义的变量,都是局部变量,它只能在函数内部被访问
变量的查找
- 当我们使用变量时,会优先在当前作用域中寻找该变量,如果有则使用,
- 如果没有则继续去上一级作用域中寻找,如果有则使用,
- 如果依然没有则继续去上一级作用域中寻找,以此类推
直到找到全局作用域,依然没有找到,则会抛出异常 NameError: name ‘a’ is not defined
def fn2():
def fn3():
print('fn3中:','a =',a)
fn3()
# fn2()
a = 20
def fn3():
# a = 10 # 在函数中为变量赋值时,默认都是为局部变量赋值
# 如果希望在函数内部修改全局变量,则需要使用global关键字,来声明变量
global a # 声明在函数内部的使用a是全局变量,此时再去修改a时,就是在修改全局的a
a = 10 # 修改全局变量
print('函数内部:','a =',a)
# fn3()
# print('函数外部:','a =',a)
命名空间(namespace)
命名空间指的是变量存储的位置,每一个变量都需要存储到指定的命名空间当中
每一个作用域都会有一个它对应的命名空间
全局命名空间,用来保存全局变量。
函数命名空间用来保存函数中的变量
命名空间实际上就是一个字典,是一个专门用来存储变量的字典
locals()用来获取当前作用域的命名空间
如果在全局作用域中调用locals()则获取全局命名空间,如果在函数作用域中调用locals()则获取函数命名空间
返回的是一个字典
scope = locals() # 当前命名空间
print(type(scope))
print(a)
print(scope['a'])
向scope中添加一个key-value
scope['c'] = 1000 # 向字典中添加key-value就相当于在全局中创建了一个变量(一般不建议这么做)
print(c)
def fn4():
a = 10
# scope = locals() # 在函数内部调用locals()会获取到函数的命名空间
# scope['b'] = 20 # 可以通过scope来操作函数的命名空间,但是也是不建议这么做
# globals() 函数可以用来在任意位置获取全局命名空间
global_scope = globals()
# print(global_scope['a'])
global_scope['a'] = 30
# print(scope)
fn4()
尝试求10的阶乘(10!)
# 1! = 1
# 2! = 1*2 = 2
# 3! = 1*2*3 = 6
# 4! = 1*2*3*4 = 24
# print(1*2*3*4*5*6*7*8*9*10)
# 创建一个变量保存结果
n = 10
for i in range(1,10):
n *= i
print(n)
创建一个可以求任意数的阶乘的函数
# 创建一个函数,可以用来求任意数的阶乘
def factorial(n):
'''
该函数用来求任意数的阶乘
参数:
n 要求阶乘的数字
'''
# 创建一个变量,来保存结果
result = n
for i in range(1,n):
result *= i
return result
# 求10的阶乘
# print(factorial(20))
递归式的函数
- 递归简单理解就是自己去引用自己!
- 递归式函数,在函数中自己调用自己!
无穷递归 如果这个函数被调用,程序的内存会溢出,效果类似于死循环
def fn():
fn()
fn()
递归是解决问题的一种方式,它和循环很像
它的整体思想是,将一个大问题分解为一个个的小问题,直到问题无法分解时,再去解决问题
递归式函数的两个要件
1.基线条件
- 问题可以被分解为的最小问题,当满足基线条件时,递归就不在执行了
2.递归条件
- 将问题继续分解的条件
- 递归和循环类似,基本是可以互相代替的,
- 循环编写起来比较容易,阅读起来稍难
- 递归编写起来难,但是方便阅读
# 10! = 10 * 9!
# 9! = 9 * 8!
# 8! = 8 * 7!
# ...
# 1! = 1
def factorial(n):
'''
该函数用来求任意数的阶乘
参数:
n 要求阶乘的数字
'''
# 基线条件 判断n是否为1,如果为1则此时不能再继续递归
if n == 1 :
# 1的阶乘就是1,直接返回1
return 1
# 递归条件
return n * factorial(n-1)
# print(factorial(10))
练习
创建一个函数 power 来为任意数字做幂运算 n ** i
10 ** 5 = 10 * 10 ** 4
10 ** 4 = 10 * 10 ** 3
…
10 ** 1 = 10
def power(n , i):
'''
power()用来为任意的数字做幂运算
参数:
n 要做幂运算的数字
i 做幂运算的次数
'''
# 基线条件
if i == 1:
# 求1次幂
return n
# 递归条件
return n * power(n , i-1)
# print(power(8,6))
创建一个函数,用来检查一个任意的字符串是否是回文字符串,如果是返回True,否则返回False
- 回文字符串,字符串从前往后念和从后往前念是一样的
abcba
abcdefgfedcba
先检查第一个字符和最后一个字符是否一致,如果不一致则不是回文字符串
如果一致,则看剩余的部分是否是回文字符串
检查 abcdefgfedcba 是不是回文
检查 bcdefgfedcb 是不是回文
检查 cdefgfedc 是不是回文
检查 defgfed 是不是回文
检查 efgfe 是不是回文
检查 fgf 是不是回文
检查 g 是不是回文
def hui_wen(s):
'''
该函数用来检查指定的字符串是否回文字符串,如果是返回True,否则返回False
参数:
s:就是要检查的字符串
'''
# 基线条件
if len(s) < 2 :
# 字符串的长度小于2,则字符串一定是回文
return True
elif s[0] != s[-1]:
# 第一个字符和最后一个字符不相等,不是回文字符串
return False
# 递归条件
return hui_wen(s[1:-1])
# def hui_wen(s):
# '''
# 该函数用来检查指定的字符串是否回文字符串,如果是返回True,否则返回False
# 参数:
# s:就是要检查的字符串
# '''
# # 基线条件
# if len(s) < 2 :
# # 字符串的长度小于2,则字符串一定是回文
# return True
# # 递归条件
# return s[0] == s[-1] and hui_wen(s[1:-1])
print(hui_wen('abcdefgfedcba'))
笔记为自己总结
来源为:尚硅谷李老师的课