函数:
函数是组织好的,可重复使用的,用来实现单一,或者关联功能的代码段。
函数能提高应用的模块性,和代码的重复利用率。函数包括内置函数和自定义函数。
函数的定义规则:
(1)函数代码块用def关键字开头,后接函数标识符名称和圆括号
(2)任何传入参数和自变量必须放在圆括号之间
(3)函数的第一行语句可以选择性地使用文档字符串——用于存放函数说明
(4)函数内容以冒号开始,并且缩进。
函数的定义语法:
def 函数名称([参数列表]): # 参数列表可有可无
函数体
def printName(): # 使用def定义一个函数
print("Hello Python")
printName() # 调用函数
调用函数:
定义一个函数只给了函数一个名称,指定了函数里包含的参数,和代码块结构。这个函数的基本结构完成以后,可以通过另一个函数调用执行,也可以直接从Python提示符执行。
函数名([参数列表])
函数名其实就是指向一个函数对象的引用,完全可以把函数名称赋值给一个变量,相当于给这个函数齐了一个别名
name = ["zhangsan", "lisi", "zhaoliu", "wangwu"]
l = len # 变量l指向了len函数
num = l(name) # 可以通过l调用到len函数
num1 = len(name) # 直接调用len函数
以上代码中,将len函数赋值其实是算法的一个优化的过程,原因是:
在调用len函数时,调用的是python的内置函数,是在python这个庞大的内置函数中搜索得到的,比较耗费时间,如果将变量l指向了len函数,相当于直接调用l的这个函数,也就是len函数,极大的优化了算法的效率。
函数形参和实参的概念:
def printName(userName): # userName是形参
print("Hello"+userName)
#调用函数
printName("张飞") # 张飞是实参
函数参数-参数默认值:
函数定义的时候,设置的参数是形参,也可以给每个参数指定一个默认。
当调用函数时候,如果没有传入实参,就使用形参的默认值
如果调用的时候传入了实参,那么程序将使用传入的实参
def printinfo(name, age = 35):
print ("Name: ", name,end="|")
print ("Age: ", age)
printinfo("zhangfei") # Name: zhangfei|Age: 35
printinfo("zhangfei",36) # Name: zhangfei|Age: 36
printinfo(36,"zhangfei") # Name: 36|Age: zhangfei 【注意:如果不加定义,实参与形参顺序应该一致】
printinfo(name="zhangfei",age=36) # Name: zhangfei|Age: 36
printinfo(age=36,name="zhangfei") # Name: zhangfei|Age: 36
函数参数-不定长参数:
def functionname([formal_args], *var_args_tuple, **var_args_dct):
function_suite
return [expression]
注意:加了星号(*)的变量名【元组】会存放所有未命名的变量参数。加了(**)【字典】会存放所有命名的变量参数
def var_fuc(a,*tuple_arg,**dict_arg):
print(a,end=",")
print(tuple_arg, end=",")
print(dict_arg)
var_fuc(1,'a','b',name='zhang',age=20) # 1,('a', 'b'),{'name': 'zhang', 'age': 20}
var_fuc(1,2,3,'a','b',name='zhang',age=20) # 1,(2, 3, 'a', 'b'),{'name': 'zhang', 'age': 20}
# 错误案例
var_fuc(1,2,3,'a','b',name='zhang',5,age=20) # Syntax Error
var_fuc(1,name='zhang',5,age=20,2,3,'a','b') # Syntax Error
注意点:不定长参数的使用比较少,但是如果使用时,必须将实参对应相应的形参,否则会出现语法错误。不定长参数的方法是写死的,形参传入的顺序不可改变。
可变对象和不可变对象的传递:
python中,string、tuples、numbers 是不可更改的对象,而list、dict、set等是可以修改的对象。
不可变类型:变量赋值a=5后再赋值a=10,这里实际是新生成一个int对象10,再让a指向它,而5则被丢弃,不是改变a的值,而是相当于新生成了一个a
可变类型:变量赋值list1=[1,2,3,4] 后 再赋值 list[2]=5则是将list1的第三个元素值更改,而本身的list1没有发生改变,仅仅是内部的一部分值发生了改变
两者的区别:不可变对象,传递的是对象的值,不是对象本身,如果修改值,修改的是另一个复制的对象,不会影响原来对象的本身。可变对象,传递对象自己。函数内部如果修改值会影响对象本身。
def changInt(a): # 不可变对象
a = 10
b = 2
changInt(b)
print(b) # 2
def changInt(a): # 不可变对象
a=[1]
b = [2]
changInt(b)
print(b) # [2]
def changInt(a): # 可变对象
a.append([1,5,6])
b = [2,3,4]
changInt(b)
print(len(b)) # 4
print(b) # [2, 3, 4, [1, 5, 6]]
def changInt(a): # 可变对象
a.extend([1,5,6])
b = [2,3,4]
changInt(b)
print(len(b)) # 6
print(b) # [2, 3, 4, 1, 5, 6]
函数返回值
函数并非总是将结果输出,相反,函数的调用者需要函数提供一些通过函数处理过后的一个或者一组数据,只有调用者拥有这个数据,才能够做一些其他的操作。也就需要函数返回一个调用者数据,这个就成为返回值,想要在函数中把结果返回给调用者,需要在函数中使用return
def max(x, y):
if x > y:
return x
else:
return y
print(max(3, 4)) # 4
一个函数返回多个数据的方式:
def divid(a, b):
shang = a//b
yushu = a%b
return shang, yushu #默认是元组
result = divid(5, 2)
print(result) # (2, 1)
def function():
# return [1, 2, 3]
# return (1, 2, 3)
return {"num1": 1, "num2": 2, "num3": 3}
return 后面可以是元组、字典、列表等,只要是能够存储多个数据的类型,就可以一次性返回多个数据
如果return后面有多个数据,那么数据默认是元组。