Function功能将一堆代码抽象成一个函数,只有调用函数的时候,代码才会运行。函数的编辑使代码可以被一次编辑,多次调用。以下是Python中函数的定义语法:
def function_name(parameters):
expressions
Python使用def(define)开始函数定义,紧接着是函数名,括号内部为函数的参数,冒号之后缩进的部分是函数内的代码块,如果想要函数有返回值,在expressions中的代码中用return返回。
# Defining a function
def myFunction():
a = 1 + 2
print(f"sum is {a}")
myFunction() # Calling a function
sum is 3
参数传递和返回值
def function_name(parameters):
expressions
parameters的位置就是函数的参数,在调用的时候传入即可。
# Positional Arguments
def describe_person(name, age):
print(f'{name} is {age} years old.')
describe_person('enoch', 25)
# Multiple Function Calls
describe_person('enoch', 23)
describe_person('enoch', 26)
# Order matters in positional arguments
describe_person('enoch', 25)
# Order doesn't matter if you specify keyword arguments
describe_person(age=25, name='enoch')
enoch is 25 years old.
enoch is 23 years old.
enoch is 26 years old.
enoch is 25 years old.
enoch is 25 years old.
我们也可以为函数提供备选的参数,在调用函数时,如果不传递参数,函数将会使用设定好的默认参数:注意=前后不能有空格
# Default values
def describe_pet(pet_name, animal_type='dog'):
print(f'{pet_name} is a {animal_type}')
describe_pet('doudou')
describe_pet('duoduo', 'cat')
doudou is a dog
duoduo is a cat
除了基本的数据类型,我们也可以将列表等其他数据类型当做参数传入:
fruits = ["a", "b", "c"]
def myFun(food):
for x in food:
print(food)
# Modifying a List in a Function
def set_to_one(input):
for i in range(0, len(input)):
input[i] = 1
number_list = [1, 2, 3, 4, 5]
set_to_one(number_list)
print(number_list)
# Preventing a Function from modifying a list
# 进行切片操作,重新生成一个变量,这样不会改变原来的值
number_list2 = [1, 2, 3, 4, 5]
set_to_one(number_list2[:])
print(number_list2)
[1, 1, 1, 1, 1]
[1, 2, 3, 4, 5]
可变参数
如果我们有很多参数要传入函数,可以将这些参数封装成一个list或tuple传入,但这样不够pythonic。我们可以使用可变参数,可变参数代表传入的参数量是不定量的。注意可变参数的定义不能出现在特定参数和默认参数前面,否则会吞噬掉这些参数,以下是可变参数的实例:
def report(name, *grades):
total_grade = 0
for grade in grades:
total_grade += grade
print(name, 'total grade is ', total_grade)
report('Ben', 80, 90, 85)
Ben total grade is 255
这里的参数grades前面有*修饰,代表该参数是一个可变参数。那么当我们调用函数的时候,我们可以在name之后输入多个参数,这些参数被调用的时候,就会被函数迭代。
- 必须是最后一位
关键字参数
我们可以使用关键字参数传入任意个含参数名的参数,这些参数名在函数定义时不用指定,在函数内部这些参数会被自动封装成字典类型(dict):
def info(name, **kw):
print('name is', name)
for k,v in kw.items():
print(k, v)
info('Mike', age=24, country='China', education='bachelor')
name is Mike
age 24
country China
education bachelor
Return语句
Return语句用于退出函数,并返回一个指定值。也就是将结果返回到调用的地方,并把程序控制权一起返回。不带参数值的return语句默认返回None。以下是return的演示:
# Returning a simple value
def get_formatted_name(first_name, last_name):
return f'{last_name.title()} {first_name.title()}'
print(get_formatted_name('hao', 'zheng'))
Zheng Hao
使用条件判断,我们可以根据不同参数返回不同的内容:
# Making an argument optional
def proposal(name, age):
if age >= 18:
return f'{name}, I want to marry you.'
else:
return f'{name}, I can\'t marry you right now'
print(proposal('Emily', 16))
print(proposal('Emily', 20))
Emily, I can't marry you right now
Emily, I want to marry you.
返回一个字典:
# Returning a dictionary
def build_person(first_name, last_name):
person = {'first': first_name, 'last': last_name}
return person
musician = build_person('hao', 'zheng')
print(musician['first'] + ' ' + musician['last'])
hao zheng
函数名规范
如果你给一个变量设定默认值,那么等号的两边是不应该有空格的,调用的时候也是一样:
如果有很多参数,那么其他行参数的缩进应该与第一行的参数缩进对应:
def function_name(
parameter_0, parameter_1, parameter_2,
parameter_3, parameter_4, parameter_5):
function body...
局部和全局变量
在def中,我们可以定义一个局部变量,这个变量x只能在函数fun中有效。出了函数,x就不能被调用了。而且即使在函数中修改了相同名字的变量,出了函数,修改是起不到作用的:
y = 2
def fun():
x = 1
y = 1
print(x)
print(y)
print(x)
2
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
d:\project\packages\Python\Python函数和参数.ipynb Cell 28 in <cell line: 8>()
<a href='vscode-notebook-cell:/d%3A/project/packages/Python/Python%E5%87%BD%E6%95%B0%E5%92%8C%E5%8F%82%E6%95%B0.ipynb#ch0000047?line=4'>5</a> print(x)
<a href='vscode-notebook-cell:/d%3A/project/packages/Python/Python%E5%87%BD%E6%95%B0%E5%92%8C%E5%8F%82%E6%95%B0.ipynb#ch0000047?line=6'>7</a> print(y)
----> <a href='vscode-notebook-cell:/d%3A/project/packages/Python/Python%E5%87%BD%E6%95%B0%E5%92%8C%E5%8F%82%E6%95%B0.ipynb#ch0000047?line=7'>8</a> print(x)
NameError: name 'x' is not defined
如何在函数内部修改某个变量,并让这个修改保下去呢?我们在内部调用的时候,就要使用global关键字,这样我们在函数内部的操作也会保存下来:
x = 2
def fun():
global x
x = 1
fun()
print(x)
1
模块函数调用
如果我们想在其他文件调用pizza.py中的函数时,使用import语句就好了:
# Importing an Entire Module (pizza.py)
import pizza
pizza.make_pizza(16, 'pepperoni')
# Using as to Give a Module an Alias # 给模块取不同的名字
import pizza as p
p.make_pizza(16, 'cheese')
# Importing Specific Functions # 只想调用其中的一个函数
from pizza import make_pizza
make_pizza(16, 'cheese')
# Using as to Give a Function an Alias
from pizza import make_pizza as mp
mp(16, 'cheese')
# Importing All Functions in a Module
from pizza import *
make_pizza(16, 'green peppers')
Lamda函数
Lambda函数也叫做匿名函数,及没有具体名称的函数。一个Lambda函数可以使用任意多的参数,但是只能有一个表达式:
x = lambda a, b, c: a + b + c
print(x(5, 6, 2)) # 12
13
为什么使用Lamda函数?当我们把lambda函数放在一个函数内部使用的时候,lambda可以很简洁地帮助我们实现小功能
def myFun(n):
return lambda a: a * n
myTripler = myFun(3)
print(myTripler(11))
递归函数
递归函数就是一个调用自己本身的函数。如果我们要计算阶乘 n! = 1 x 2 x 3 x … x n,用函数fact(n)表示则为:fact(n) = n! = 1 x 2 x 3 x … x (n-1) x n = (n-1)! x n = fact(n – 1) x n,用递归的方式写出来就是:
def fact(n):
if n == 1:
return 1
return n * fact(n - 1)
递归函数逻辑清晰,定义也简单。理论上所有递归函数都可以写成循环的方式,但逻辑不如递归清晰。
程序入口判断
有时我们希望某文件被当做模板引进的时候,部分代码不要被执行。如果当前脚本含有单元测试,那么我们在其他地方调用此脚本的时候,测试部分就没有必要了。我们可以做以下的条件判断:
if __name__ == '__main__':
# statements
如果当前文件只是被作为模块引进的话,在程序运行时,statements部分的代码是不会被执行的。
Homework
list1 = [1, 2, 3]
list2 = [4, 5, 6]
list3 = [4, 5, 6, 7, 8]
def addSum(
list1, list2
):
sum = []
length1 = len(list1)
length2 = len(list2)
if length1 <= length2:
for i in range(length1):
temp_sum = list1[i] + list2[i]
sum.append(temp_sum)
for j in range(length2-length1):
sum.append(list2[length1+j])
return sum
if length1 > length2:
for i in range(length2):
temp_sum = list1[i] + list2[i]
sum.append(temp_sum)
for j in range(length2-length1):
sum.append(list2[length1+j])
return sum
addSum(list1, list2)
addSum(list1, list3)
[5, 7, 9, 7, 8]
list1 = [1, 2, 3, 5]
list2 = [2, 4, 9, 10, 12, 48]
sum = []
def myFun(list1, list2, sum):
shorterList, longerList = [], []
if len(list1) <= len(list2):
shorterList, longerList = list1, list2
else:
shorterList, longerList = list2, list1
for i in range(len(shorterList)):
sum.append(shorterList[i] + longerList[i])
for i in range(len(shorterList), len(longerList)):
sum.append(longerList[i])
myFun(list1, list2, sum)
print(sum)
[3, 6, 12, 15, 12, 48]