def是创建函数的关键字,调用函数是函数名加上括号。
def MYFirstFunction():
print('这是创建的第一个函数')
print('我表示很鸡冻。。。。。')
# 调用函数
MYFirstFunction()
# 运行结果:
这是创建的第一个函数
我表示很鸡冻。。。。。
从下面代码中传入的实参不一致,我们可以看到结果中是不一样的。
def MYSecondFunction(name):
print('欢迎' +name + '来到我的python函数中。')
MYSecondFunction('张三')
MYSecondFunction('李四')
MYSecondFunction('王五')
# 运行结果:
欢迎张三来到我的python函数中。
欢迎李四来到我的python函数中。
欢迎王五来到我的python函数中。
如下代码,定义两个函数,每个函数都有两个形参,第一个add函数调用,直接赋值,打印出信息。add1函数使用print调用,但是在代码中有一个return内置的BIF函数来返回给add1,所以使用print可以打印出信息。
def add(num1,num2):
suum = num1 + num2
print('计算结果如下:')
print(suum)
def add1(num1,num2):
return (num1 + num2)
add(999,150)
print(add1(7,8))
# 结果如下:
计算结果如下:
1149
15
形参:在定义函数名后面括号中的参数我们叫形参(parameter) 实参:在调用函数的时候传入的参数为实参(argument)。 函数文档:在函数的编写过程中,如果很大的代码体,方便其他人快速识别代码。
def MyFUN(name):
'函数定义过程中的name是叫形参'
# 以为ta只是一个形式,表示占据一个参数位置
print('传递进来的' + name + '叫做实参,因为Ta是具体的参数值!')
MyFUN('张三')
print(MyFUN.__doc__)
print(help(MyFUN))
# 结果如下:
传递进来的张三叫做实参,因为Ta是具体的参数值!
函数定义过程中的name是叫形参
Help on function MyFUN in module __main__:
MyFUN(name)
函数定义过程中的name是叫形参
None
关键字参数:定义在调用函数的时候,通过参数名赋值,例如:MyFUN(name=‘张三’) 默认参数:定义了默认值的参数叫默认参数,在函数定义参数的过程中赋值就变为了默认参数。
def animal(name='猴子',action='爬树'):
print(name + '喜欢' + action)
animal()
animal('游泳','鸭子')
animal(action='游泳',name='鸭子')
# 结果如下:
猴子喜欢爬树
游泳喜欢鸭子
鸭子喜欢游泳
收集参数:在形参的前面加一个*号,代表收集参数,可以收集多个参数,例如:MyFUN(*name)。实际上是python把收集参数的这个形参name设置为了一个元组,然后再从这个元组中调用实参。如果一个函数除了有收集参数还有其他参数,请把这个参数设置为默认参数,如果不设置默认参数,函数会报错,把所有的实参默认给收集参数。
def add(*num,mon='大猩猩'):
print('这个函数收集参数的长度是:', len(num))
print('第二个参数是:',num[2])
print('这个函数的默认参数是:' + mon)
add('大白兔','小乌龟','大象','河马','豹子',mon = '猴子')
# 结果如下;
这个函数收集参数的长度是: 5
第二个参数是: 大象
这个函数的默认参数是:猴子
在编程语言中,我们认为函数function是有返回值的,而过程procedure是简单、特殊并且没有返回值的。 ‘python只有函数没有过程’,为什么这么说呢,例如我们定义一个函数,打印一个hello,word,如下:
def hello():
print('Hello,word!')
temp = hello()
print(temp)
print(type(temp))
# 结果如下:
Hello,word!
None
<class 'NoneType'>
python是可以返回多个值,我们可以想到列表,列表中使用逗号是可以变为元组的,如下例,我们可以看到python中的return是把这组数据打包成一个数据返回。
def MyFun():
return [1,'list','done']
print(MyFun())
def MyFun1():
return 1,'list','done'
print(MyFun1())
# 结果如下:
[1, 'list', 'done']
(1, 'list', 'done')
def discounts(price,rate):
final_price = price * rate
return final_price
old_price = float(input('请输入原价:'))
rate = float(input('请输入折扣率:'))
new_price = discounts(old_price,rate)
print('打折后的价格是:',new_price)
print('这里试图打印局部变量 final_price的值: ', final_price )
# 结果如下:
请输入原价:100
请输入折扣率:0.8
打折后的价格是: 80.0
Traceback (most recent call last):
File "D:/Backup/PyCharm/study_py.py", line 25, in <module>
print('这里试图打印局部变量 final_price的值: ', final_price )
NameError: name 'final_price' is not defined
由上面的例子单中,不难发现,我们在打印局部变量的时候,提示报错,final_price是没有被定义的。也就是说我们定义的这个final_price只是在discounts这个函数中生效,出来这个函数,这个变量就无效了,实际上,python在调用函数的时候,会把这些代码存储在栈中,运行完一条代码,就会把这段代码从栈中的空间删除。上面的代码中old_price,new_price这些就是全局变量,他比局部变量有更大的权限,它的作用域是整个代码,真个模块,但是我们在修改全局变量的时候也要注意,如果在函数内部修改全局变量,python会创建一个和全局变量一样的局部变量,如下例中的old_price:
def discounts(price,rate):
final_price = price * rate
old_price = 50
print('这里试图打印修改后的变量old_price的值: ', old_price )
return final_price
old_price = float(input('请输入原价:'))
rate = float(input('请输入折扣率:'))
new_price = discounts(old_price,rate)
print('打折后的价格是:',new_price)
print('这里试图打印修改后的全局变量old_price的值: ', old_price )
# 结果如下:
请输入原价:100
请输入折扣率:0.8
这里试图打印修改后的变量old_price的值: 50
打折后的价格是: 80.0
这里试图打印修改后的全局变量old_price的值: 100.0
全局变量,在函数内部中是可以访问的,但是我们不要试图去修改一个全局变量,因为python会使用屏蔽shadowing方式来保护全局变量,怎么样来保护呢? python会创建一个和全局变量一样的变量,并把它设置为局部变量。但是如果我们想要去修改全局变量,可以实现吗,答案是肯定的。我们需要使用到global关键字,举个例子,如下:
count = 5
def MyFUN():
count = 10
print(count)
MyFUN()
print(count)
# 结果如下:
10
5
# 我们可以把global关键字给加上在测试下:
count = 5
def MyFUN():
global count
count = 10
print(count)
MyFUN()
print(count)
# 结果如下:
10
10
python中的函数其实内部也是可以定义函数的,我们可以称之为内嵌函数或者内部函数,关于内嵌函数我们需要注意的是:内部函数的作用域是在外部函数之内。也就是说Fun2函数是在Fun1函数内部生效,离开Fun1函数,Fun2函数就不生效了。来举个例子
def Fun1():
print('Fun1正在被调用')
def Fun2():
print('Fun2正在被调用')
Fun2()
Fun1()
# 结果如下:
Fun1正在被调用
Fun2正在被调用
python中的闭包从表现形式上定义为如果一个内部函数对外部作用域(但不是在全局作用域)的变量进行引用,那么内部函数就会被认为是闭包(closure)。
def Funx(x):
def Funy(y):
return x * y
return Funy
# return Funy这里注意一下,因为我们python里面几乎所有的东西都是对象,我们说你在python里面记住他的名字就可以了,不需要记住他是什么数据什么类型什么变量,我们可以直接把函数对象给直接返回。
i = Funx(8)
print(i)
print(type(i))
print(i(5))
print(Funx(8)(5))
print(Funy(5))
# 结果如下:
<function Funx.<locals>.Funy at 0x0355B610>
<class 'function'>
40
40
Traceback (most recent call last):
File "D:/Backup/PyCharm/study_py.py", line 54, in <module>
print(Funy(5))
NameError: name 'Funy' is not defined
# 我们来理解下闭包的概念,如果在一个内部函数里,对于Funx,Funy属于内部函数;对在外部作用域,这个函数Funy的外部作用域也就是Funx整个函数空间的变量x对它进行引用。达到这两点,我们就说这个Funy是闭包.
def Fun1():
x = 5
def Fun2():
x *= x
return x
return Fun2()
Fun1()
# 结果如下:
Traceback (most recent call last):
File "D:/Backup/PyCharm/study_py.py", line 63, in <module>
Fun1()
File "D:/Backup/PyCharm/study_py.py", line 62, in Fun1
return Fun2()
File "D:/Backup/PyCharm/study_py.py", line 60, in Fun2
x *= x
UnboundLocalError: local variable 'x' referenced before assignment
注意:UnboundLocalError: local variable ‘x’ referenced before assignment 出现这个报错的原因是:因为在执行return Fun2()的时候,那么他就会跑到Fun2里面去执行,整个Fun1的内部空间,x=5,它属于Fun2中的全局变量,但是对于整个代码来说,他是一个局部变量,其实x=5是非全局变量的外部变量;在Fun2中的x和Fun1中的x不是一个变量,和之前全局变量和局部变量中讲到的一样,在python函数中定义一个全局变量,python通过shadowing的方式来屏蔽掉这个全局变量,创建一个和全局变量相同的变量x,但是这个x是局部变量,也就是说Fun1中的x=5并没有传入到Fun2中,Fun2中这个x是局部变量。
如果想要实现Fun1中的这个x传给Fun2,我们可以把Fun2中的这个形参设置为x,如下图即可实现x的平方。
def Fun1():
x = 5
def Fun2(x):
x *= x
return x
return Fun2(x)
print(Fun1())
在python2中,
def Fun1():
x = [5]
def Fun2():
x[0] *= x[0]
return x[0]
return Fun2()
print(Fun1())
# 结果如下:
25
python3的世界中,又发明了一个关键字nonlocal,这个关键字和global关键字的使用方式一样,把Fun1中的x变量设置为Fun2中直接引用。
def Fun1():
x = 5
def Fun2():
nonlocal x
x *= x
return x
return Fun2()
print(Fun1())
# 结果如下:
25
Lambda函数又称匿名函数,匿名函数就是没有名字的函数,函数没有名字也行?当然可以啦。有些函数如果只是临时一用,而且它的业务逻辑也很简单时,就没必要非给它取个名字不可。
python写一些执行脚本时,使用lambda就可以省下定义函数过程,比如说我们只是需要写个简单的脚本来管理服务器时间,我们就不需要专门定义一个函数,然后在写调用,使用lambda就可以使得代码更加精简 对于一些比较抽象并且整个程序执行下来只需要调用一两次的函数,有时候给函数起个名字也是比较头疼的问题,使用lambda就不需要考虑命名的问题了。 简化代码的可读性,由于普通的屌丝函数阅读经常要调到开头def定义部分,使用lambda函数就可以省去这样的步骤.
def Fun(x):
return x * 2 + x
print(Fun(5))
# 结果如下:
15
g = lambda x : x * 2 + x
print(g(5))
# 结果如下:
15
# 由上面的结果中我们可以看到两段代码的结果是一样,lambda可以简化代码量。
filter() 过滤器,filter() 函数用于过滤序列,过滤掉不符合条件的元素,返回一个迭代器对象,如果要转换为列表,可以使用 list() 来转换。
该接收两个参数,第一个为函数,第二个为序列,序列的每个元素作为参数传递给函数进行判,然后返回 True 或 False,最后将返回 True 的元素放到新列表中。下面我们举个例子:
print(filter(None,[0,1,False,True]))
print(list(filter(None,[0,1,False,True])))
# 结果如下,通过下面的结果我们可以查看到filter函数可以把前面的None给过滤掉,打印出一个新的list。
<filter object at 0x0345D0D0>
[1, True]
# 编写一个0到9的列表,去除其中的奇数
def odd(x):
return x % 2
temp = range(10)
show = filter(odd,temp)
print(list(show))
# 结果如下:
[1, 3, 5, 7, 9]
# 我们可以看到上面定义了一个函数,代码便较多,如过使用lambda表达式,我们来看看
print(list(filter(lambda x : x % 2,range(10))))
# 得到的结果是:
[1, 3, 5, 7, 9]
# 可以看到使用lambda的表达式我们一行代码就搞定了,对于python来说是很美观的。
map() 会根据提供的函数对指定序列做映射。
第一个参数 function 以参数序列中的每一个元素调用 function 函数,返回包含每次 function 函数返回值的新列表。
print(list(map(lambda x : x * x , range(5))))
# 结果如下:
[0, 1, 4, 9, 16]
什么叫递归呢?递归就是在函数内部调用自己的函数被称之为递归。
python中可以调用sys模块,sys.setrecursionlimit(100) #可以设置递归的层数,python3默认是100层。
求一个整数的阶乘,例如给的是5,阶乘就是:54321
# 如果不使用函数,这个阶乘该如何写呢?简单的用一个for函数就可以实现。
multiplication = 1
n = int(input('请输入一个数字:'))
for i in range(1,n):
multiplication *= i
print(multiplication)
# 如果我们需要使用一个函数来写呢?但是是非递归版本。
def factorial(n):
result = n
for i in range(1,n):
result *= i
return result
number = int(input('请输入一个正整数: '))
result = factorial(number)
print("%d 的阶乘是:%d" % (number,result))
# 递归版本如下
def factoria2(m):
if m == 1:
return 1
else:
return m * factoria2(m-1)
number2 = int(input('请输入一个正整数: '))
result2 = factoria2(number2)
print("%d 的阶乘是:%d" % (number2,result2))
def rabbit(n):
if n == 1 or n ==2:
rabbit_num = 1
else:
rabbit_num = rabbit(n-1) +rabbit(n-2)
return rabbit_num
print(rabbit(int(input("请输入一个整数:"))))
# 结果如下:
请输入一个整数:20
6765
def hanoi(n,x,y,z):
if n == 1:
print(x,'-->',z)
else:
hanoi(n-1,x,z,y) # 将前n-1个盘子从x移动到y上
print(x,'-->',z) # 将第n个盘子从x移动到z上
hanoi(n-1,y,x,z) # 将y上的n-1个盘子移动到z上
n = int(input('请输入一个数字:'))
hanoi(n,'X','Y','Z')
# 结果如下:
请输入一个数字:4
X --> Y
X --> Z
Y --> Z
X --> Y
Z --> X
Z --> Y
X --> Y
X --> Z
Y --> Z
Y --> X
Z --> X
Y --> Z
X --> Y
X --> Z
Y --> Z