目录python
秉承着一切皆对象的理念,咱们再次回头来看函数(function)。函数也是一个对象,具备属性(可使用dir()查询)。做为对象,它还能够赋值给其它对象名,或者做为参数传递。git
# 变量能够被传递 name = 'jason' x = name print(x) # jason print(id(name), id(x)) # 3085464224688 3085464224688
# 尝试函数像变量同样被传递 def func(): print('from func') print(func) # <function func at 0x0000016E5E062E18> f = func # 其实指向的也是函数func 指向的函数体代码的内存地址 print(f) # <function func at 0x000001B4D0D92E18> f() # from func print(id(func), id(f)) # 3085463137816 3085463137816
def func(): print("from func") def index(args): print(args) args() # 函数主要必定义(先定义)就能够在任意地方调用 print("from index") index(func) # <function func at 0x000001B7429A2E18> # from func # from index
def index(): print('index') def func(): print('func') return index res = func() # 将返回的函数名index 赋值给变量res # func print(res) # <function index at 0x000001EF64362E18> res() # index
def func(): print('func') l = [1, 2, func, func()] # 定义的时候默认执行了func(),因此下面先打印了 func # func # func函数没有返回值,因此默认是None print(l) # [1, 2, <function func at 0x0000013931C92E18>, None]
函数对象小练习app
def register(): print("注册了") pass def login(): print("登陆了") pass def shopping(): print("购物了") pass def output_func_list(): print("----- 请选择功能!") for key in func_list: print(f"---- {key}.{func_list[key][1]}") func_list = { 0: [register, '注册'], 1: [login, '登陆'], 2: [shopping, '购物'], } while True: output_func_list() chose_func = input("请输入功能编号(q 退出系统):").strip() if chose_func.isdigit(): # 执行相应功能 chose_func = int(chose_func) # 判断输入的编号在不在功能列表里 if chose_func in func_list: func_list[chose_func][0]() # 取到功能函数名,加括号调用 else: print("您输入的功能编号不存在,请从新输入!") elif chose_func.lower() in ['q', 'quit']: print("感谢您的使用,祝您生活愉快~") break else: print("请正确输入数字!")
函数的嵌套调用: # 在函数内部调用其余函数函数
def index(): print('index') def func(): index() # 在定义 func 函数的时候不会直接调用 index 的方法 --> 函数定义的时候不执行代码 print('func') func() # index # 经过 func()函数内部调用了index() 函数,打印出了 index # func
函数的嵌套调用能够将复杂的逻辑简单化测试
小练习:写一个能够求四个数中的最大值ui
def my_max(x, y): if x > y: return x return y def my_max4(a, b, c, d): res = my_max(a, b) res = my_max(res, c) res = my_max(res, d) return res print(my_max4(1, 5, 7, 1)) # 7
def outer(): x = 1 print("outer") def inner(): print("inner") inner() # inner() # 会报错,在外部没法访问内部内容 outer() # outer # inner
实如今外部调用 outer函数的内部函数 innercode
# 想在外部调用inner 可经过把内部的函数名当作外部函数的返回值来返回给外部 def outer(): x = 1 print("outer") def inner(): print("inner") return inner # 把 inner 函数当作函数的返回值返回给 outer函数的调用者 res = outer() # outer res() # 变相调用inner # inner 实现代码
名称空间: # 存放的是变量名 与 变量值 的内存地址 绑定关系的地方 ,后文可能称之为命名空间。对象
访问变量的值: # 要想访问一个变量的值,必须先去名称空间拿到对应的名字,才能访问变量的值生命周期
命名空间分为:内置名称空间,全局名称空间,局部名称空间 三大类ip
内置名称空间: # python 解释器提早已经定义好了的名字(已经存放到了内置名称空间中了)
print("hello world") max(1, 44, 62, 15) len('26515f1asfafqw') sum([1, 2, 3, 4, 5]) # 像上面的print max len sum 并无定义就能够值使用,它们就是python解释器提早定义好了的函数,属于内置命名空间的
全局命名空间:文件级别的代码
x = 1 if x == 1: y = 2 print(y) # 2 for i in [1, 2]: print(i) print(i) # 1 # 2 # 2 # 上面的 x y z 都在全局名称空间,不要觉得缩进的就是局部的(if、 for、 while 不管嵌套,多少层,他们内部所建立的名字都是全局名称空间的)
局部命名空间: (目前所学)函数体内建立的名字都属于局部名称空间(最外层的函数名是属于全局名称空间的)
def func(): username = 'jason' # print(username) # 会报错 NameError: name 'username' is not defined func()
至于为何上面的 print(username) 为何会报错,学完下面的知识你就知道啦。
''' 名称空间的生命周期 内置名称空间:(最长)只要 python解释器启动,立马建立 关闭 python解释器时自动销毁 全局名称空间: 只要右键运行 py文件就会自动建立 py文件程序运行结束自动销毁 局部名称空间:(动态建立动态销毁)函数被调用的时候自动建立 函数执行结束后当即销毁 '''
''' # 名称空间生命周期结束 -- > 里面存的变量与指向值的内存地址解绑,内存中的值等待垃圾回收机制回收 # def 删除变量 -- > 里面存的变量与指向值的内存地址解绑,内存中的值等待垃圾回收机制回收 ---> 等同于名称空间里删除了一个变量(绑定关系) # 垃圾回收机制:垃圾回收机制隔一段时间就会检查一次,内存中的值若是没有变量指向它(引用),那垃圾回收机制就会把它清除掉(释放内存) # 若是屡次检查都有变量等指向它,那就会把它等级提高,检查频率就会变低 '''
验证思路: # 找一个三个地方都有的东西来验证(好比 len、max等,暂时忽略命名规范不能与关键字重复) , # 分别注释来测试其查找顺序(全局、局部 )
len = '我是全局名称空间的len' def func(): len = '我是局部名称空间的len' print(len) print(len) # 这里是全局的位置 # 我是全局名称空间的len ''' # 把全局的len 注释掉,就去找了内置的len print(len) # 是全局的位置 # <built-in function len> ''' func() # 我是局部名称空间的len
''' (******)名称空间的查找顺序 1.须要先肯定当前的在哪(全局、局部),大前提 1.1 站在全局:全局 >>> 内置 1.2 站在局部:局部 >>> 全局 >>> 内置 1.2.2 站在局部的内部(多个局部嵌套):局部 >>> 上一级局部 >>> 上一级局部 >>> .... >>> 全局 >>> 内置 会在做用域同级的先后(这句代码先后的同级语句)去找,而后再上一级 2.函数在定义阶段查找名字的顺序(范围)就已经固定了, 不会由于函数的调用位置变化而变化(*******) 能够在函数定义的时候写个注释,指出他查找的位置,防止逻辑复杂了搞不清楚 '''
python中的做用域有 全局做用域 与 局部做用域 , 全局做用域: # 全局有效: 内置名称空间、全局名称空间 都属于全局做用域 , 局部做用域: # 局部有效:局部名称空间
# 尝试修改不可变类型的全局变量 x = 1 def func(): x = 2 # 实质是又建立了一个局部变量 x func() print(x) # 局部没法修改不可变类型的全局变量 # 1 # 尝试修改可变类型的局部变量 x = [] def func(): x.append('嘿嘿嘿') func() print(x) # 修改为功,局部能够修改可变类型的全局变量 # ['嘿嘿嘿'] # 全局访问不了局部的变量,因此不展开研究
小结论: # 局部没法修改不可变类型的全局变量 , # 局部能够修改可变类型的全局变量 (前提:在不使用 global 和 nonlocal 关键字的状况下)
经过 global 关键字在局部修改全局,修改多个用 , 隔开
x = 1 # 不可变类型 username = 'jason' def func(): global x,username x = 999 # 修改全局变量,而不是建立局部变量 username = 'egon' func() print(x, username) # 999 egon
经过 nonlocal 关键字在局部修改局部,修改多个用 , 隔开
def func(): x = 1 def index(): x = 2 index() print(x) func() # 1 # 想就在 index 里把 x 改了 def func(): x = 1 def index(): nonlocal x x = 2 index() print(x) func() # 2