写在博客的开头
nick说:人生疾苦唯有自救,这是你相信IT的最后一次机会。这个时候必须得逼自己一把,只有对自己够狠才能慢慢强大。昨天看一哥们在博客上说每天大喊一遍python第一java第二,python大法无所不能,给自己以一个乐观积极的态度好好学习天天向上。加油,希望我们每一个人都不负光阴。
可变长参数
*形参名
def f1(*args):#调用时有多少个位置实参就接收多少个
print(args)#*args(约定俗成的),用元组接收多余的位置实参
**形参
def f1(**kwargs):
print(kwargs)#用字典接收多余的关键字实参
以上内容很important,以下内容仅作了解(Nick说以后很少用到)
*实参
def f1(a,b,c,d,e,f,g):
print(a,b,c,d,e,f,g)
lt = [1,2,3,4,5,6,7]
f1[*lt]#*lt把列表中的元素打散成位置实参一次传给位置形参(这个过程其实就是解压缩)
**实参
def f1(z,b):
print(z,b)
dic = {'z':,'b':2}
f1(**dic)#**dic把字典打散成关键字实参然后传给函数f1
函数对象
Python中一切皆对象,函数是第一类对象,即函数可以被当作数据处理。
def func():
print('from func')
prnit(func)
<function func at 0x10af72f28>
一、函数对象的四大功能
-
引用
x = 'hello nick' y = x f = func#这么做的的原因是:这样f()和func()就是同一个函数了 print(f)
<function func at 0x10af72f28>
-
当做参数传给一个函数
len(x) def foo(m): m() foo(func)#func是一个函数名,将func作为实参传给foo这个函数,形参m用于接收func,执行到foo函数体里面就得到了func()实现了对func函数的调用。
from func
-
可以当做函数的返回值
def foo(x): return x res = foo(func) print(res) res()#func被return回来赋给res从而实现了对func函数的调用
<function func at 0x10af72f28>
from func -
可以当作容器类型的元素
l = [x] function_list = [func] function_list[0]()#这个就很叼了,在调用登录注册等多个函数时把函数名作为字典的value,然后通过这种方法去调用函数贼方便。
from func
练习
def register():
print('register')
def login():
pass
def withdraw():
pass
def shoppong():
print('shopping')
func_dict = {
'1':register,
'2':login,
'3':withdraw,
'4':shopping,
}
print('''
1 注册
2 登录
3 提现
4 购物
''')
while Ture:
choice = input('请选择你需要的功能(输入q退出):')
if choice == 'q':
break
func_dict[choice]()#函数当做容器类型的元素
函数的嵌套
所谓嵌套就是在函数内部再定义函数,不过函数内部定义的函数,无法在函数外部使用。
如
def f1():
def f2():
print('from f2')
f2()
f2()
# NameError: name 'f2' is not defined
这个就可以使用:
def f1():
def f2():
print('from f2')
f2()
f1()
from f2
函数嵌套的调用
如下面一个比较四个数大小得出最大值的函数
def compare_1(x,y):
if x>y:
return x
else:
return y
def compare_2(a,b,c,d):
res1 = compare_1(a,b)
res2 = compare_1(res1,c)
res3 = compare_1(res2,d)#牛掰哦这种比较方法
return res3
#compare_2(1,2,3,4)
print(compare_2(1,2,3,4))
4
名称空间和作用域
一、名称空间
名称空间(name spaces):在内存管理那一章节时,我们曾说到变量的创建其实就是在内存中开辟了一个新的空间。但是我们一直在回避变量名的存储,其实在内存中有一块内存存储变量名与变量间的绑定关系的空间,而这个空间称为名称空间。
1.1 内置名称空间
内置名称空间:存放Pyhton解释器自带的名字,如int、float、len
生命周期:在解释器启动时生效,在解释器关闭时失效。
1.2 全局名称空间
全局名称空间:除了内置和局部的名字之外,其余都存放在全局名称空间。
生命周期:在文件执行时生效,在文件执行结束后失效。
1.3 局部名称空间
局部名称空间:用于存放函数调用期间函数体产生的名字,如下面代码的f2
。
生命周期:在文件执行时函数调用期间时生效,在函数执行结束后失效。
def f1():
def f2():
print('from f2')
f2()
f1()
1.4 加载顺序
由于.py文件是由Python解释器打开的,因此一定是在Python解释器中的内置名称空间加载结束后,文件才开始打开,这个时候才会产生全局名称空间,当文件内某一个函数被调用时,才会产生局部名称空间,因此名称空间的加载顺序为:内置》全局》局部》。
1.5 查找顺序
由于名称空间是用来存放变量名与变量值之间的绑定关系的,所以但凡要查找名字,一定要从三者之一找到,查找顺序为:
从当前所在的位置开始查找,如果当前所在的位置为局部名称空间,则查找顺序为:局部》全局》内置。
x = 1
y = 2
len = 100
def func():
y = 3
len = 1000
print(f"y:{y}")
print(f"len:{len}")
func()
y: 3
len: 1000
def func():
printx
x = 10
func()
10
二、作用域
域指的是区域,作用域就是作用的区域。
2.1 全局作用域
全局作用域:全局有效,全局存活,包含内置名称空间和全局名称空间。
#全局作用域
x = 1
def bar():
print(x)
bar()
1
2.2 局部作用域
局部作用域只包含局部名称空间。
def f1():
def f2():
def f3():
print(x)
x = 2
f3()
f2()
f1()
2
2.3 注意点
作用域关系在函数作用阶段就固定死了,与函数的调用无关。
# 作用域注意点
x = 1
def f1(): # 定义阶段x=1
print(x)
def f2():
x = 2
f1()
f2()
1
很绕的一个例子,画个图看一下:
程序运行的时候内存空间的开辟如图所示,所以当f1()运行的时候,程序会先在f1()的局部作用域内找x的值,找不到就去全局找而不是去f2()的作用域内找。再看下面一个例子:
x = 1
def f2():
x = 2
def f1(): # 定义阶段x=1
print(x)
f1()
f2()
2
这个f1执行完就回去f2找x的值,因为f1的作用域在f2里面。
2.4 函数对象+作用域应用
# 作用域应用
def f1():
def inner():
print('from inner')
return inner
f = f1() # 把局部定义的函数放在全局之中
def bar():
f()
bar()#相当于f1()(),相当于inner()
from inner
三、补充知识点
3.1 global关键字(尽量少用,Nick说容易懵逼)
修改全局作用域中的变量。
x = 1
def f1():
x = 2
def f2():
# global x # 修改全局
x = 3
f2()
f1()
print(x)
1
x = 1
def f1():
x = 2
def f2():
global x # 修改全局
x = 3
f2()
f1()
print(x)
3
3.2 nonlocal关键字(最好不要使用,容易把自己弄懵逼)
修改作用域中的变量。
x = 1
def f1():
x = 2
def f2():
# nonlocal x
x = 3
f2()
print(x)
f1()
2
x = 1
def f1():
x = 2
def f2():
nonlocal x
x = 3
f2()
print(x)
f1()
3
3.3 注意点(very important)
- 可变数据类型可以打破上述一切规则。
lt = [10]
def f1():
lt.append(12)
lt[0] = 11
f1()
print(lt)
[11, 12]
- 在局部如果想修改全局的不可变类型,需要借助global声明,声明为全局变量,即可直接修改。