知晓函数的妙用,但是学习起来略微头疼。
这个需要反复看,多练手:
主要是gloab\local\lambda初级使用和说明,还需继续努力学习。
print('=========一、函数基础和学习==============')
"""
为什么要学习函数:
1、最大化的代码重用和最小化代码冗余
2、流程的分解。
语句 例子
Calls myfunc("spam", "eggs", meat=ham)
def, def adder(a, b=1, *c):
return return a+b+c[o]
global def changer():
global x; x ='new
nonlocal def changer():
nonlocal; x ='new'
yield def squares(x):
for i in range(): yield** 2
lambda Funcs [lambda x: x*2, lambda x: x*3]
"""
def times(x,y):
return x*y
print(times(2,4)) #调用
x=times(3.14,4)
print('x:',x)
print(times('NI',4))
print('=========函数:寻找交集 \并集\合集 (&、|、)==============')
def like(seq1,seq2): #取相同 在1 且在2
res=[]
for x in seq1:
if x in seq2: #如果if用for 会变成4遍循环
res.append(x)
return res
def unlike(seq1,seq2): #取不同 在1 不在2
res=[]
for x in seq1:
if x not in seq2: #如果if用for 会变成4遍循环
res.append(x)
return res
def union(seq1,seq2): #取不同 在1 或者2
res=list(seq1)
for x in seq2:
if x not in seq1: #如果if用for 会变成4遍循环
res.append(x)
return res
s1 = 'spam'
s2 = 'scam'
print(like(s1,s2),unlike(s1,s2),union(s1,s2))
print([x for x in s1 if x in s2])
x = like([1,3,4],(1,4))
print(x)
#集合 { } 或者set([ ]) 知识点又忘记了。。。麻蛋
s3=set(['s','p','a','m'])
s4= set(['s','c','a','m'])
print(s3|s4,s3&s4,s3-s4)
print('=========函数:作用域==============')
X=99
def func():
X=88
print(X)
func() #作用域def范围内
print('X:作用域范围外:',X)
print('=========函数:变量名解析LEGB原则==============')
"""
1、变量名引用分为三个作用域进行查找:首先是本地,之后是函数内(如果有的话),之后全局,最后是内置。
2、在默认情况下,变量名赋值会创建或者改变本地变量。
3、全局声明和非本地声明将赋值的变量名映射到模块文件内部的作用域。
4、当在函数中使用未认证的变量名时, Python搜索4个作用域[本地作用域(L),之后是上一层结构中def或 lambda的本地作用域(E),之后是全局作用域(G),最
后是内置作用域(B)]并且在第一处能够找到这个变量名的地方停下来。如果变量名在这次搜索中没有找到, Python会报错。正如我们在第6章学到的那样,变量
名在使用前首先必须赋值过。
5、当在函数中给一个变量名赋值时(而不是在一个表达式中对其进行引用),Python总是创建或改变本地作用域的变量名,除非它已经在那个函数中声明为全局变量。
6、当在函数之外给一个变量名赋值时(也就是,在一个模块文件的顶层,或者是在交互提示模式下),本地作用域与全局作用域(这个模块的命名空间)是相同的。
"""
X =99 #Global scope
def func(Y):
#local scope
Z= X+Y
return Z
print(func(1),func(3))
def hider():
open ='spam'
open('data.txt')
print('=========函数:global语句==============')
"""
globalPython语句是中唯一看起来有些像声明语句的语句。但是,它并不是一个类型或
大小的声明,它是一个命名空间的声明。它告诉 Python函数打算生成一个或多个全局变
量名。也就是说,存在于整个模块内部作用域(命名空间)的变量名。
1、全局变量是位于模块文件内部的顶层的变量名。
2、全局变量如果是在函数内被赋值的话,必须经过声明。
3、全局变量名在函数的内部不经过声明也可以被引用。
"""
# x=88
# def func():
# global x
# x=99
# func()
# print(x)
def f1():
# global s9
s9=88
def f2():
s9=77 #如果赋值,就是77 没赋值就是 88
print(s9)
return f2
action =f1()
action()
print('=========函数:工厂函数、lambda==============')
"""
像def一样, lambda表达式引入了新的本地作用域。多亏了嵌套作用域查找层, lambda
能够看到所有在所编写的函数中可用的变量。因此,以下的代码现在能够运行,但仅仅
是因为如今能够使用嵌套作用域法则了。
"""
def func():
l=4
action=(lambda n:l ** n)
return action
l=func()
print(l(2))
def makeAction():
acts=[]
for i in range(5):
acts.append(lambda n,i=i: i**n)
return acts
acts=makeAction()
print('acts:',acts[0](2),acts[2](2),acts[4](2))
print('=========函数:nonlocal只在一条函数有意义=============')
"""
nonlocal语句是global的近亲,前面已经介绍过 global。 nonlocalglobal和一样,声明
了将要在一个嵌套的作用域中修改的名称。和 global的不同之处在于, nonlocal应用于
一个嵌套的函数的作用域中的一个名称,而不是所有def之外的全局模块作用域;而且
在声明 nonlocal名称的时候,它必须已经存在于该嵌套函数的作用域中它们可能只
存在于一个嵌套的函数中,并且不能由一个嵌套的def中的第一次赋值创建。
这块看的头疼,等以后有用到继续深入学习
"""
# num = int(input('输入任意的正整数x:'))
# num1 = int(input('输入任意的正整数y:'))
# sum=0
# if num1>=num:
# for i in range(num,num1+1):
# sum += i
# else:
# for i in range(num1,num+1):
# sum +=i
# print(sum)
#
# x = int(input('输入任意的正整数x:'))
# y = int(input('输入任意的正整数y:'))
# if y>=x:
# sum=sum(i for i in range(x,y+1))
# else:
# sum=sum([i for i in range(y,x+1)])
# print(sum)
print('=========二、参数=============')
"""
1、不可变参数“通过值”进行传递。像整数和字符串这样的对象是通过对象引用而不是拷贝进行传递的,但是因为你无论怎样都不可能在原处改变不可变对象,实际的
效果就很像创建了一份拷贝。
2、可变对象是通过“指针”进行传递的。例如,列表和字典这样的对象也是通过对象引用进行传递的,这一点与C语言使用指针传递数组很相似:可变对象能够在函数
内部进行原处的改变,这一点和C数组很像。
"""
print('=========1、共享引用=============')
def f(a):
a=99 #改变函数局部值
b=88
f(b) #a、b都指向88的值
print(b) #b未改动
def changer(a,b):
a=2
b[0]='spam'
X=1
L=[1,2]
changer(X,L)
print(X,L)
"""
·因为a是在函数作用域内的本地变量名,第一个赋值对函数调用者没有影响,它仅仅把本地变量a修改为引用一个完全不同的对象,并没有改变调用者作用域中的名
称的绑定。这和前面的例子中的情况是相同的。
·b也是一个本地变量名,但是它被传给了一个可变对象(在调用者作用域中叫做L的列表)。因为第二个赋值是一个在原处发生的对象改变,对函数中b[]进行赋值的
结果会在函数返回后影响L的值。
实际上, changer中的第二条赋值语句没有修改b,我们修改的是b当前所引用的对象的一部分。这种原处修改,只有在修改的对象比函数调用生命更长的时候,才会影响到调
用者。名称L也没有改变——它仍然引用同样的、修改后的对象,但是,就好像L在调用后变化了一样,因为它引用的值已经在函数中修改过了。
"""
#上面内容参考下面的比较:
x1=1
a=x1
a=2
print(x1)
L=[1,2]
b=L
b[0]='spam'
print(L)
print('=========2、避免参数修改=============')
# L=[1,2]
# changer(X,L[:])
print('=========3、模拟参数输出=============')
def mult(x,y):
x=2
y=[3,4]
return x,y
X=1
L=[1,2]
X,L=mult(X,L)
print('X,L分别为:',X,L)
print('=========4、特定的参数匹配模型=============')
"""
1、关键字参数:通过参数名进行匹配
调用者可以定义哪一个函数接受这个值,通过在调用时使用参数的变量名,使用name=value这种语法。
2、默认参数:为没有传入值的参数定义参数值
如果调用时传入的值过于少的话,函数能够为参数定义接受的默认值,再一次使用语法name=value
3、可变参数:收集任意多基于位置或关键字的参数
函数能够使用特定的参数,它们是以字符*开头,收集任意多的额外参数(这个特
性常常叫做可变参数,类似C语言中的可变参数特性,也能够支持可变长度参数的列表)。
4、可变参数解包:传递任意多的基于位置或关键字的参数
调用者能够再使用*语法去将参数集合打散,分成参数。这个“*”与在函数头部的
“*”恰恰相反:在函数头部它意味着收集任意多的参数,而在调用者中意味着传递任意多的参数。
5、Keyword--only参数:参数必须按照名称传递
在 Python3.0中(不包括Python2.6中),函数也可以指定参数,参数必须用带有关
键参数的名字(而不是位置)来传递。这样的参数通常用来定义实际参数以外的配置选项。
"""
"""
语法 位置 解释
func(value) 调用者 常规参数:通过位置进行匹配
func(name=value) 调用者 关键字参数:通过变量名匹配
func(*sequence) 调用者 以name传递所有的对象,并作为独立的基于位置的参数
func(**dict) 调用者 以name成对的传递所有的关键字/值,并作为独立的关键字参数
def func(name) 函数 常规参数:通过位置或变量名进行匹配
def func(name=value) 函数 默认参数值,如果没有在调用中传递的话
def func(*name)) 函数 匹配并收集(在元组中)所有包含位置的参数
def func(**name) 函数 匹配并收集(在字典中)所有包含位置的参数
def func(*args,name) 函数 参数必须在调用中按照关键字传递
def func(*,name=value) (Python 3.+)
"""
#关键字参数
def f(a,b,c): print(a,b,c)
f(1,2,3)
#关键字参数
f(c=3,b=2,a=1)
print('=========4.1、默认参数=============')
#默认参数
def f(a,b=2,c=3):print(a,b,c)
f(1)
f(a=4)
f(1,5)
f(1,c=8)
print('=========4.2、默认参数与默认参数的混合=============')
def func(spam,eggs,toast=0,ham=9):
print(spam,eggs,toast,ham)
func(1,2)
func(1,ham=1,eggs=0)
func(1,2,3,4)
func(toast=1,eggs=2,spam=3)
print('=========4.3、收集参数=============')
def f(*args):print(args) #集合
f()
f(1) #特殊
f(1,2,3,4)
def f(**args):print(args) #字典
f()
f(a=1,b=2)
def f(a,*pargs,**kargs): print(a,pargs,kargs)
f(1,2,3,x=1,y=2) #1传递给a, 2,3收集到pargs元组 4,5收集到kargs 关键字典中
print('=========4.3、解包参数=============')
def func(a,b,c,d): print(a,b,c,d)
args=(1,2)
args += (3,4)
func(*args)
def func(**args):print(args)
args={'a':1,'b':2,'c':3}
args['e']=5
func(**args)
print('=========4.4、应用函数通用性=============')
def tracer(func,*pargs,**kargs):
print('calling:',func.__name__)
return func(*pargs,**kargs)
def func(a,b,c,d):
return a+b+c+d
print(tracer(func,1,2,c=3,d=4))
print('=========4.5、Key-only参数=============')
def kwonly(a,*b,c):
print(a,b,c)
kwonly(1,2,c=3)
kwonly(a=1,c=3)
# kwonly(1,2,3) #没有关键字无法运行
def kwonly(a,*,b='spam',c='ham'):
print(a,b,c)
kwonly(1)
kwonly(1,c=3)
kwonly(a=1)
kwonly(c=3,b=2,a=1)
# kwonly(1,2) #出错 kwonly() takes 1 positional argument but 2 were given