1、函数
开发程序的时候,若多个地方需要用到同一块代码块,为了提高编写的效率,把这些代码块进行封装集成到某个地方,便于多次的调用,这就是函数。
1.1、函数定义
语法:
def 函数名():
封装的逻辑
函数需要用def作为开头,算作标识。函数名的定义规则跟变量命名一样,需要见名知意,之后再按照命名规范来。函数名后一定要加小括号(),小括号后跟冒号:。之后,新开一行进行缩进,缩进后写封装的逻辑。
1.2、函数调用
函数定义好后,如何使用呢?
函数名() 的方式即可调用写好的函数。
示例:
def print_info():
print("*" * 20)
print("*")
print("*")
print("*")
print("*" * 20)
print_info()
print("调用函数成功")
1.3、函数注释
这里有两种注释方法。
第一种:
将函数注释写在定义的函数上方。
示例:
写完注释后,将鼠标左键放在上面,会出现这种提示框。
第二种:
将注释写到函数内部,注意注释需要放在前面。
第二种方法最常用。
示例:
def print_info():
'''
函数注释:
函数名:print_info
功能:打印信息
'''
print("*" * 20)
print("*")
print("*")
print("*")
print("*" * 20)
help(print_info)
通过help方法可以打印注释。
1.4、函数参数
若函数需要对数据进行处理,那么数据从哪里来呢?
答案就是:参数。
参数分为两种,一种为:形参。另一种为实参。
示例:
def use_methods(parm1,parm2):
assert isinstance(parm1,int)
assert isinstance(parm2,int)
if parm1 > parm2:
print(f"Max is {parm1}")
else:
print(f"Max is {parm2}")
int_value1 = 10
int_value2 = 20
use_methods(int_value1,int_value2)
示例中的parm1和parm2就是形参,它没有实际的意义,只有形式意义。它的存在可以理解为占位,等待实际参数的传递。int_value1和int_value2就是实参,它们是这个函数实际处理的数据。这个函数的功能就是比较大小,但如果像示例一样没加注释,初学者可能看不懂,传的值也未必是数字,因此需要加上断言防止用户传错值。
1.5、传递参数的类型:
可变类型和不变可类型。
不可变类型:传递不可变类型的参数,即使对形参的值进行更改,也不会改变原来的值。
示例:
def func_type(int_value):
if int_value > 10:
int_value = 999
else:
int_value = -999
print(int_value)
int_value = 8
func_type(int_value)
print(int_value)
对于不可变类型的参数,你可以理解为传递了一个复制体,其本身是不会被修改的,因为内存地址的值不允许改变,改变了就新开辟一个内存地址。
可变类型:传递可变类型的参数,一旦形参的值变了,原来的值也会变。
示例:
def func_type(list_value):
list_value[0] = 999
print(list_value)
list_value = [1,2,3]
func_type(list_value)
print(list_value)
可变数据类型可以理解为将自己传递到形参中,因为可变数据类型可以更改内存的值。学过指针概念的,其相当于传一个指针到函数中。
1.6、函数返回值
函数完成功能后,需要给调用者返回一些结果,称返回值。
语法:
def 函数名():
封装的逻辑
return 某个值
示例:
def return_value(parm1,parm2):
max_one = 0
if parm1 > parm2:
max_one = parm1
else:
max_one = parm2
return max_one
int_value1 = 10
int_value2 = 20
max = return_value(int_value1,int_value2)
print(max)
return的作用不仅仅只是返回一个值,也代表着函数的结束。
当函数中执行到return这里,不管后面还有啥逻辑代码,都会跳过,直接跳出整个函数。
示例:
def return_value(parm1,parm2):
if parm1 > parm2:
return parm1
else:
return parm2
int_value1 = 10
int_value2 = 20
max = return
每次执行到return的时候,后面的直接跳过了。
当然,return不仅仅可以返回一个值,也可以返回多个值。
示例:
def return_value(parm1,parm2):
if parm1 > parm2:
return parm1,parm2
else:
return parm2,parm1
int_value1 = 10
int_value2 = 20
max1,max2 = return_value(int_value1,int_value2)
print(max1,max2)
根据不同的返回值,接收数据的形式也不一样。
示例:
def return_value(parm1,parm2):
if parm1 > parm2:
return [parm1,parm2]
else:
return [parm2,parm1]
int_value1 = 10
int_value2 = 20
[max1,max2] = return_value(int_value1,int_value2)
max = return_value(int_value1,int_value2)
print(max1,max2)
print(max)
可以解构形式的接收,也可以整体接收。
1.7、参数类别
Python中函数参数分为:位置参数、默认参数、可变参数、关键字参数和命名关键字参数。
位置参数:就是按照形参的顺序,依次传值,不能多也不能少。
示例:
#位置参数
def pos(parm1,parm2):
return parm1,parm2
int_value1 = 10
int_value2 = 20
max1,max2 = pos(int_value1,int_value2)
print(max1,max2)
max1,max2 = pos(int_value1)
max1,max2 = pos(int_value1,int_value2,int_value1)
默认参数:形参可以设定一个默认值,传值时如果不传,默认参数会使用默认值。
示例:
def default_value(parm1,parm2 = 20):
return parm1,parm2
parm1,parm2 = default_value(10)
print(parm1,parm2)
parm1,parm2 = default_value(10,30)
print(parm1,parm2)
注意:默认参数必须放置于位置参数后面,放前面会报错。且,默认参数最好用不可变类型的数据,避免逻辑出错。
可变参数:传入的参数数量是可变的。通过*args的方式,会将传入的值放入元组中。(元组不能修改)
示例:
def change_value(*args):
print(type(args))
for value in args:
print(value)
change_value(1,2,3,4,5)
change_value(*[1,2,3,4])
传值的时候可以一个个传,也可将列表、元组这种可迭代对象传入,注意前面加个*,标识。
关键字参数:允许传入多个带参数名的参数,内部会组装为一个字典。使用**kwargs接收。
示例:
def power_value(**kwargs):
print(type(kwargs))
print(kwargs)
power_value(name="XiaoLi",age=20,address="china")
power_value(**{"name":"XiaoLi","age":20,"address":"china"})
允许以参数名 = 数值 的形式传值,也可以用 **dict字典 的方式传值,注意**是标识。
命名关键字参数:传值时必须加上参数名,否则python解释器会报错。这是固定参数的一种方式,一般用*标识。
示例:
def name_value(parm1,parm2,*,parm3,parm4):
print(parm1,parm2,parm3,parm4)
name_value(parm1=1,parm2=2,parm3=3,parm4=4)
name_value(1,2,parm3=3,parm4=4)
name_value(1,2,3,4)
一般传值时参数名可加可不加,但使用命名关键字参数,*后面的参数名必须加。命名关键字参数可以设定默认值
*注意:如果命名关键字前面已经有了可变参数*args,就不用加了
可组合:这五种参数可以组合到一起使用,但顺序必须是:位置参数-->默认参数-->可变参数-->命名关键字参数-->关键字参数。
2、全局变量和局部变量
作用域:变量生效的范围。
全局变量:函数外部定义的变量,作用域是全局。
局部变量:函数内部定义的变量,作用域是函数内部。
全局变量在整个程序运行中都可以访问,但局部变量只生效于定义的那个函数中。
示例:
int_value = 20
def local_value():
int_value1 = 30
print(int_value1)
print(int_value)
local_value()
print(int_value)
print(int_value1)
2.1、局部变量与全局变量同名
若函数中第一次出现变量 = 某个值,且这个变量与全局变量同名,函数调用时优先会将这个同名变量识别为局部变量,且不会对全局变量造成影响。
示例:
int_value = 20
def local_value():
int_value = 30
print(int_value)
local_value()
print(int_value)
但如果出现的变量没有定义(没有变量名 = 某个值),那么优先被认定为全局变量。
示例:
int_value = 20
def local_value():
print(int_value)
local_value()
print(int_value)
如果变量既不是全局变量,也不是局部变量,编译器会报错。
它们的优先级一定是先局部,再全局。
注意:避免产生冲突,命名尽量要唯一。
2.2、改变全局变量
首先,一般情况下是不能直接改全局变量的,因为在你改的时候有一个赋值过程,这一过程会被编译器认定为定义,于是乎函数内部的全局变量被认定为局部变量,自然就报错了。
示例:
int_value = 20
def local_value():
print(int_value)
int_value += 2
local_value()
print(int_value)
那怎么让编译器知道这是个全局变量,且我要更改这个全局变量的值呢?
这就要用到:global。
示例:
int_value = 20
def local_value():
global int_value
print(int_value)
int_value += 2
print(int_value)
local_value()
print(int_value)
用global声明的变量会被认定为全局变量,这时我们就可以对其重新赋值了,新的值也会替换原来的值。
注意:除非不得已,一般情况下还是少用全局变量,其权限太大,容易给程序带来未知的逻辑错误。