pycharm退出test模式
由于各种原因,pycharm有test字段,或者有test的函数时,会莫名奇妙的进入test模式,有时候怎么也跳不出来,要退出这种模式,在运行键旁边进入‘Edit configuration’模式,可以看到左侧Python下有两个文件,如果进入了test模式,就会有‘Python test’一栏,这时点击‘-’号去掉这栏下的文件即可
定义函数
格式:
def 函数名(参数):
函数体
函数名其实就是指向一个函数对象的引用,完全可以把函数名赋值给一个变量,相当于给这个函数起了一个别名
def Pname(): #当前函数不放参数 print('大家好我是杰大哥!') Pname() #调用函数 执行了函数里面的代码 pri = Pname #将函数名赋值给另一个变量,相当于给当前函数取一个别名 pri() #pri()的作用等于Pname()
函数参数分类
总体上分为形参和实参
1、必备参数
向函数传递参数的方式有很多,通过实参和形参的顺序对应,这就是位置实参,参数的个数不能少,不能多,参数的位置要一一对应,只有位置一致,才能被正确匹配
2、关键字参数
关键字实参是传递给函数的名称-值对;直接在实参中将名称和值关联起来,因此向函数传递实参时不会混淆,使用关键字参数允许函数调用时参数的顺序与声明时不一致,因为 Python 解释器能够用参数名匹配参数值
3、默认参数
函数定义的时候,设置的参数是形参;那么也可以给每个形参指定一个默认值,当调用函数时,如果没有传入实参,就使用形参的默认值,如果调用的时候传入了实参,那么程序将使用传入的实参
4、不定长参数
可能需要一个函数能处理比当初声明时更多的参数,这些参数叫做不定长参数;加了星号(*)的变量名会存放所有未命名的变量参数,按元组的类型存放,加了(**)会存放所有命名的变量参数,按字典的类型存放
def Pname(userName): #userName为形参 形参的名字是自定义的 print('大家好我是%s同学!'%userName) Pname('刘德华') #传递了一个实参 '刘德华' #必备参数 def getInfo(name,address): print('大家好我叫%s,我来自%s'%(name,address)) getInfo('刘德华','香港') #第一个实参对应了第一个形参,第二实参对应第二个形参 # getInfo('刘德华') #形参有两个,调用的时候,实参也要传递两个,否则会报错 #参数的个数不能少,不能多。 参数的位置要一一对应 #关键字参数 def getInfo(name,address): print('大家好我叫%s,我来自%s'%(name,address)) getInfo(name='刘德华',address='香港') #给实参加上关键字 关键字对应着形参 #参数的默认值 def getInfo(name,address = '香港'): #默认值参数,就是在声明函数的时候给形参赋值 print('大家好我叫%s,我来自%s'%(name,address)) getInfo('刘德华') #有默认值的形参,可以不用传递 getInfo('刘德华','九龙') #传递参数时,会覆盖原来的默认值 ''' 不定长参数 *args 是接受所有未命名的参数(关键字) **agrs2 是接受所有命名的参数(带关键字的) 输出为 大家好我叫刘德华,我来自九龙 ('a', 'b', 'c', 'd') {'age': 18} ''' def getInfo(name,address,*args,**agrs2): print('大家好我叫%s,我来自%s'%(name,address)) print(args) #args 是一个元组类型 输出为('a', 'b', 'c', 'd') print(agrs2) #字典数据类型 输出为{'age': 18} getInfo('刘德华','九龙','a','b','c','d',age = 18)
可变对象与不可变对象的传递
不可变类型:整数、字符串、元组。如当调用函数fun(a)时,传递的只是a的值,没有影响a对象本身。在 fun(a)内部修改 a 的值,只是修改另一个复制的对象,不会影响 a 本身
可变类型:列表、字典。如当调用函数fun(la)时,则是将 la 真正的传过去,修改后fun外部的la也会受影响
#不可变对象的传递——值的传递 def fun(args): args = 'hello' #重新赋值 print(args) #输出为hello str1 = 'baby' #声明一个字符串的变量 不可变数据类型 fun(str1) #将该字符串传递到函数中 print(str1) #输出为baby 并没有被改变 #可变对象的传递——引用传递 def fun(args): args[0] = 'hello' #重新赋值 print(args) #输出为['hello', 'come on'] list01 = ['baby','come on'] #声明一个列表 可变数据类型 fun(list01) #将该字符串传递到函数中 print(list01) #输出为['hello', 'come on'] 传递的是对象本身,函数里面被修改了值,原对象也会跟着修改
函数返回值
1、return语句
return语句用于退出函数,选择性的向调用者返回一个表达式。直接return的语句,即不写任何表达式,默认返回None,return后语句不再执行,函数调用过程彻底结束,用一个变量可以接受多个返回值,并会保存在一个元组中
def max(x, y): if x > y: return x #结束函数的运行 并且将结果返回给调用的地方 else: return y #后面的代码不会执行 print('我没有被执行') #没有执行print num = max(1,2) #声明一个变量num 接受调用函数后的返回值 print(max(1,2)) #输出为2 返回值会返回到调用的地方 def sum(x,y): #return返回多个返回值 return x,y num = sum(1,2) #用一个变量接受多个返回值,会保存在一个元组中 print(num) #输出为(1, 2) num1,num2 = sum(1,2) #两个变量分别对应的接受返回值 print(num1) #输出为1 print(num2) #输出为2
2、yield语句
迭代器是一个可以记住遍历的位置的对象, 迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束,迭代器只能往前不会后退,迭代器有两个基本的方法:iter() 和 next(),其中字符串,列表或元组,集合对象都可用于创建迭代器
dict={'打野':'Bengi','中单':'Faker'} list=[1,2,3,4] it1 = iter(list) #创建迭代器对象 it2 = iter(dict) print (next(it1)) #输出为1 迭代器的下一个元素 print (next(it1)) #输出为2 for i in it1: #it1已经变为迭代器,所有会接着上边的运行 print(i) #输出为3 4 print (next(it2)) #输出为打野 print (dict[next(it2)]) #输出为Faker
yield 的作用就是把一个函数变成一个generator,带有 yield 的函数不再是一个普通函数,Python 解释器会将其视为一个生成器,与return类似,都可以返回值,但不一样的地方,yield可以返回多次值,而return只能返回一次
在调用生成器运行的过程中,每次遇到 yield 时函数会暂停并保存当前所有的运行信息,返回yield的值。并在下一次从当前位置继续运行,可以通过for循环或者手动调用 next() 的方法
def getNum(n): i = 0 while i <= n: yield i #将函数变成一个generator i+=1 a = getNum(5) #把生成器赋值给一个变量a print(next(a)) #输出为0 使用生成器 通过 next()方法 print(next(a)) #输出为1 输出yield返回的值 for i in a: #for循环遍历一个生成器 接着上边的运行 print(i,end=' ') #输出为2 3 4 5 ''' 使用生成器可以达到延迟操作的效果,所谓延迟操作就是指在需要的时候 产生结果而不是立即产生就结果,节省资源消耗,和声明一个序列不同的 是生成器,在不使用的时候几乎是不占内存的 ''' # a = [x for x in range(10000000)] #这样生成一个很多数据的列表会占用很大的内存 # print(a) grt = (x for x in range(10000000)) #这是一个生成器 不是元组推导式,就没有元组推导式这一说法 print(grt) #输出为<generator object <genexpr> at 0x00000000028231B0> print(next(grt)) #输出为0 print(next(grt)) #输出为1 print(next(grt)) #输出为2
3、生成器-send
a = yield 1 ,等号右边是一个yield 1,所以先要执行yield 1,然后才是赋值,yield把1值返回到了调用者那里,因为执行等号右边的yield就是暂停,所以不会对a赋值,换句话说a = yield 1 只执行了一半,那这个表达式的下一步操作:赋值,但这时没有值给a了,而send()里面的值的作用是把值传进当前的yield
''' 输出为 0 None 1 我是被传入的值 2 ''' def gen(): i = 0 while i < 5: temp = yield i #不是赋值操作——使用了yield之后是一个生成器 print(temp) #因为yield之后返回结果到调用者的地方,暂停运行,赋值操作没有运行 i+=1 a = gen() print(next(a)) print(next(a)) print(a.send('我是被传入的值')) #可以将值发送到 上一次yield的地方
变量的作用域
1、全局变量
全局变量是声明在函数外部的变量,定义在函数外的拥有全局作用域
#全局变量 def test1(): print(a) #输出为1 print(id(a)) #输出为8791399764800 def test2(): print(a) #输出为1 print(id(a)) #输出为8791399764800 a = 1 test1() test2() print(a) #输出为1 print(id(a)) #输出为8791399764800——大家使用的是同一个变量,全局变量
2、局部变量
局部变量就是在函数内部定义的变量,不同的函数,可以定义相同的名字的局部变量,但是各用各的不会产生影响
#局部变量:声明在函数内部的变量是局部变量 def test1(): a = 1 print(a) #输出为1 print(id(a)) #输出为8791399764800 def test2(): a = 2 print(a) #输出为2 无法使用test1函数中定义的局部变量 print(id(a)) #输出为8791399764832 test1() test2() #print(a) #局部变量的作用于只在于函数中,外部无法使用,会报错
3、可变类型的全局变量
对于不可变类型的全局变量来说,要在函数中修改需要global声明
对于可变类型的全局变量来说,要在函数中修改可以不使用global声明
def test1(): global a #声明全局变量a a = 2 #值以及内存地址都变了 print(a) #输出为2 print(id(a)) #输出为8791399764832 def test2(): a = 3 print(a) #输出为3 print(id(a)) #输出为8791399764864 a = 1 print(id(a)) #输出为8791399764800 test1() test2() print(a) #输出为2 print(id(a)) #输出为8791399764832
匿名函数
定义函数的过程中,没有给定名称的函数就叫做匿名函数;Python中使用lambda表达式来创建匿名函数
lambda匿名函数的表达式规则是: lambda 参数列表: 表达式
# 没有参数的lambda表达式 s = lambda : '杰大哥牛逼' #通过lambda声明一个匿名函数,并且赋值给s,冒号后的表达式会返回 print(s()) #通过s调用匿名函数 # 声明一个参数 s = lambda x: x*2 print(s(3)) #输出为6 # 声明两个参数 s = lambda x,y: x+y #lambda相当于def;x,y相当于形参;x+y是表达式,相当于return后的返回值 print(s(3,4)) #输出为7 ''' if 条件: 代码块哦 else: 代码块 矢量化的三元运算符 条件成立的内容 if 条件 else 条件不成立的内容 ''' s = lambda x, y: x if x > 2 else y print(s(1, 4)) #输出为4
递归函数
递归就是子程序(或函数)直接调用自己或通过一系列调用语句间接调用自己
def main(n): print('进入第%d层梦境'%n) if n == 3: print('到达潜意识区,原来我最爱的人是你!开始醒来') else: main(n+1) print('从第%d层梦境醒来'%n) main(1) #回到调用的地方 ''' 第一次调用:进入第1层梦境 第二次调用:进入第2层梦境 第三次调用:进入第3层梦境 进入 if 到达潜意识区,原来我最爱的人是你!开始醒来 从第3层梦境醒来 结束第三次调用 从第2层梦境醒来 结束第二次调用 从第1层梦境醒来 结束第一次调用 '''