函数
- 定义:对代码块和功能的封装和定义
def 函数名 (): 函数体 return #没有return或者 return没有的时候, 返回None. 一个值的时候返回的是它本身 多个值 返回的是一个元祖 函数名() #调用函数 谁调用返回值就给谁
形参和实参
形参的分类 1.位置参数 按照位置来申明形参 2.默认参数 和实参的关键字参数 区分开 位置参数必须放默认参数前边 实参的分类 1.位置参数 按照位置,给形参赋值 2.关键字参数 按照形参的名字给参数赋值 3.混合参数 位置参数放关键字参数前面 传参 把实参赋值给形参的过程
三元运算符
def func(a,b) c=a if a>b else b print(c) func(3,4) #4
动态传参
def func(*food): "*"表示接受任意内容 动态位置传参
顺序:位置参数- *args- 默认值参数- **kwargs(接受动态关键字参数)
传参顺序
位置参数>*args>默认值参数>**kwargs
动态传参的另一种方式
def fun(*args): print(args) lst = [1, 4, 7] fun(lst[0], lst[1], lst[2]) fun(*lst) # 可以使⽤用*把⼀一个列列表按顺序打散 s = "⾂臣妾做不不到" fun(*s) # 字符串串也可以打散, (可迭代对象)
在参数位置上给一个序列,列表,可迭代对象前面加*,表示把这个序列按顺序打散
形参位置上的*表示把接受到的参数组合成一个元祖
def fun(**kwargs): print(kwargs) dic = {'a':1, 'b':2} fun(**dic)
字典也可以打散,不过需要用两个*
命名空间
在python解释器开始执⾏行行之后, 就会在内存中开辟⼀一个空间, 每当遇到⼀一个变量量的时候, 就 把变量量名和值之间的关系记录下来, 但 是当遇到函数定义的时候, 解释器只是 把函数名读入内 存, 表⽰示这个函数存在了了, ⾄至于函数内部的变量量和逻辑, 解释器是不关⼼心的. 也 就是说⼀一开始 的时候函数只是加载进来, 仅此⽽而已, 只有当函数被调⽤用和 访问的时候, 解释器才会根据函数 内部声明的变量量来进⾏行行开 辟变量量的内部空间. 随着函数执⾏行行完毕, 这些函数内部变量量占⽤用的空 间也会随着函数执⾏行行完毕⽽而被清空
命名空间的分类
1.全局命名空间:我们直接在朋友文件中,函数外声明的变量都属于全局命名空间
:作用域 全局和局部,加载是在运行之后,代码之前
2.局部命名空间:在函数中声明的变量会放在局部命名空间
:作用域 全局和局部,加载是在运行代码的时候
3.内置命名空间:存放Python解释器为我们提供的名字,list,tuple,str,int这些都是内置命名空间
:作用域 在局部,加载是在调用的时候
覆盖
先来后到
从先到后:内置全局局部
同一个名字:局部覆盖全局和内置,全局覆盖内置
加载顺序:
1内置命名空间
2全局命名空间
3局部命名空间(函数被执行的时候)
取值顺序:
1. 局部命名空间
2. 全局命名空间
3. 内置命名空间
作用域
作用域就是作用范围,按照生效范围来看分为全局作用域和局部作用域
全局作用域:包含内置命名空间和全局命名空间.在整个文件的任何位置都可以使用(遵循从上到下逐步执行)
局部作用域:在函数内部可以使用
作用域命名空间
1全局作用域:全局命名空间+内置命名空间
2局部作用域:局部命名空间
我们可以通过globals()函数来查看全局作用域中的内容,
通过locas()函数来查看局部作用域中的变量和函数信息
a = 10 def func(): a = 40 b = 20 def abc(): print("哈哈") print(a, b) # 这里使用的是局部作用域 print(globals()) # 打印全局作用域中的内容 print(locals()) # 打印局部作用域中的内容 abc() func() 打印顺序 40 20 {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x000001DBA784C278>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'D:/作业/day 08.py', '__cached__': None, 'a': 10, 'func': <function func at 0x000001DBA77F2E18>} {'abc': <function func.<locals>.abc at 0x000001DBA94DA8C8>, 'b': 20, 'a': 40} 哈哈 函数的嵌套
只要遇见了()就是函数的调用.如果没有()就不是函数的调用
关键字global和nonlocal
global:在局部改全局
全局变量不应该随意被修改
可变数据类型在局部中的修改都不需要声明且在全局
a = 100 def func(): global a # 加了个global表示不再局部创建这个变量了. 而是直接使用全局的a a = 28 print(a) func() print(a) global表示. 不再使用局部作用域中的内容了了. ⽽而改⽤用全局作⽤用域中的变量量
nonlocal:在小局部改大局部,两个局部之间一定有嵌套关系
lst = ["麻花藤", "刘嘉玲", "詹姆斯"] def func(): lst.append("马云") # 对于可变数据类型可以直接进行访问. 但是不能改地址. 说白了. 不能赋值 print(lst) func() print(lst) #nonlocal 表⽰示在局部作⽤用域中, 调⽤用⽗父级命名空间中的变量.
a = 10 def func1(): a = 20 def func2(): nonlocal a a = 30 print(a) func2() print(a) func1() 结果: 加了了nonlocal 30 30 不不加nonlocal 30 20
函数名的本质(函数是第一类对象的概念)
函数名可以复制
可以作为容器中的一项
可以做参数
可以做返回值
变量和值的关系
返回值的本质:是返回的值,而不是某个变量
def func(): a = 1 return a # 返回值不是a,而是a代表的变量值1 b = func() print(b)
def func(): a = 1 b = 2 return b+b # 返回的不是算式,而是b+b的结果4 b = func() print(b) func 函数的内存地址
函数名加括号==调用
函数的地址加括号==调用
函数名 可以赋值 代码如下
def f(): print(123) f() # a = b = c = abc = f abc = f a = f b = f c = f f() abc() a() b() c()
容器类型:列表 元祖 字典 集合
函数名可以作为容器类型中的一项,可以做字典的key
def f1(): print('娃哈哈') def f2(): print('qqxing') l = [f1,f2] print(l) f1_func = l[1] f1_func() l[1]() for f in l: f()
函数名可以作为函数的参数
def login(): print('欢迎登陆') def index(auth): auth() print('欢迎来到首页') index(login)
函数名可以作为函数的返回值
def login_failed(): print('登陆失败') def index(): print('欢迎来到首页') def login(usr,pwd): if usr == 'alex' and pwd == 'sb': return index else: return login_failed res_func = login('alex','ssb') res_func()
函数名函数调用返回值
def f(): pass f() f是函数名 f()是函数的调用 f()得到的结果是返回值
函数名也会变
def func(): print('123') print(func) f1 = func print(f1) f1和func的内存地址一样