在前面我们用了一些函数,比如:input()、print()、len()、range()等。这些都是python内置的函数,可以直接拿来用。
python除了内置函数外,还支持自定义函数。
自定义函数:即将一段有规律的、可重复使用的代码定义成函数,从而达到一次编写、多次调用的目的。
例:写一个类似于len() 函数作用的函数:用来统计字符串、列表等长度
# 写一个类似于 len() 函数的ll函数
def ll(str):
sum = 0
for i in str:
sum += 1;
return sum
s = 'hello'
print(ll(s)) # 5
**函数:**将常用的代码以固定的格式封装(包装)成一个独立的模块,只要知道这个模块的名字就可以重复使用它,这个模块就叫做函数。
Python 函数支持接收多个( ≥0 )参数,不同之处在于,Python 函数还支持返回多个( ≥0 )值。
def 函数名(参数列表):
//实现特定功能的多行代码
[return [返回值]]
例:定义一个比较大小的函数:
# 比较数字大小的函数:
def compare(str1,str2):
str = str1 if str1 > str2 else str2
return str
max = compare(10,20)
print('两数中,较大的数为:%d' %max) # 20
函数中的 return 语句可以直接返回一个表达式的值。
def compare(str1,str2):
return str1 if str1 > str2 else str2
[返回值] = 函数名([形参值])
函数的说明文档,本质就是一段字符串,只不过作为说明文档,字符串的放置位置是有讲究的,函数的说明文档通常位于函数内部、所有代码的最前面。
def compare(str1,str2):
'''
比较两个数的大小
:param str1: 第一个参数
:param str2: 第二个参数
:return: 返回值
'''
str = str1 if str1 > str2 else str2
return str
max = compare(10,20)
print('两数中,较大的数为:%d' %max) # 20
help(compare)
def demo(obj): # obj 就是形式参数
print(obj)
str = 'hello'
demo(str) # str就是实际参数
python中,根据实际参数的类型不同,函数参数的传递方式可分为 2 种,分别为值传递和引用(地址)传递:
值传递和引用传递的区别是,函数参数进行值传递后,若形参的值发生改变,不会影响实参的值;
而函数参数继续引用传递后,改变形参的值,实参的值也会一同改变。
def demo(obj):
obj += obj
print('形参的值为:', obj)
print('-----值传递------')
a = 'hello'
demo(a)
print('实参的值:', a)
print('----引用传递-----')
lst = [1,2,3]
demo(lst)
print('实参的值:', lst)
-----值传递------
形参的值为: hellohello
实参的值: hello
----引用传递-----
形参的值为: [1, 2, 3, 1, 2, 3]
实参的值: [1, 2, 3, 1, 2, 3]
位置参数,有时也称必备参数,指的是必须按照正确的顺序将实际参数传到函数中。
调用函数时传入实际参数的数量和位置都必须和定义函数时保持一致。
实参和形参数量必须一致。(不可以多传和少传)
实参和形参位置必须一致。(参数类型,位置要一致)
# 求长方形的边长
def side(length, wideth):
sum = (length + wideth) * 2
return sum
print(side(3)) # 缺少一个参数,报错:TypeError: side() missing 1 required positional argument: 'wideth'
print(side(3,4,5,)) # 多了参数,报错:TypeError: side() takes 2 positional arguments but 3 were given
print(side('hello', 4)) # 参数类型不一致,报错:TypeError: can only concatenate str (not "int") to str
print(side(4,3)) # 参数位置错了,没报错,但是结果与预期的不符
关键字参数:是指使用形式参数的名字来确定输入的参数值。通过此方式指定函数实参时,不再需要与形参的位置完全一致,只要将参数名写正确即可。
# 关键字参数:
def my_str(str1, str2):
print('str1:', str1)
print('str2:', str2)
# 位置参数:
my_str('hello', 'world')
# 关键字参数
my_str('hello', str2='china')
my_str(str2='java', str1='linux')
str1: hello
str2: world
str1: hello
str2: china
str1: linux
str2: java
在调用有参函数时,既可以根据位置参数来调用,也可以使用关键字参数来调用。
在使用关键字参数调用时,可以任意调换参数传参的位置。
也可以位置和关键字混合传参,这时就需要位置参数必须在关键字参数前面。
默认参数:参数设置默认值,即在定义函数时,直接给形式参数指定一个默认值。
def 函数名(...,形参名,形参名=默认值):
代码块
注意,在使用此格式定义函数时,指定有默认值的形式参数必须在没默认值参数的后面,否则会产生语法错误。
注意:
def func(a,*b,**c): # 1、位置参数,2、任意位置参数 3、任意关键字参数
print(a,b,c)
func(1,2,3,4,5,x=6,y=7) # 1 (2, 3, 4, 5) {'x': 6, 'y': 7}
None 不表示 0,也不表示空字符串,而表示没有值,也就是空值。
print(type(None)) #
对于所有没有 return 语句的函数定义,Python 都会在末尾加上 return None,使用不带值的 return 语句(也就是只有 return 关键字本身),那么就返回 None。
return 在函数中可以出现多次,但是只要一个得到执行,就结束函数的执行。
def add(num1, num2):
sum = num1 + num2
return sum
result = add(10, 20)
print(result) # 30
return 可返回多个值。
作用域:就是变量的有效范围,表示变量可以在哪个范围内使用。
有些变量可以在整段代码的任意位置使用,有些变量只能在函数内部使用,有些变量只能在 for 循环内部使用。
在函数内部定义的变量,它的作用域也仅限于函数内部,出了函数就不能使用了,我们将这样的变量称为局部变量。
函数的参数也属于局部变量,只能在函数内部使用。
全局变量的默认作用域是整个程序,即全局变量既可以在各个函数的外部使用,也可以在各函数内部使用。
在函数体内定义全局变量。即使用 global 关键字对变量进行修饰后,该变量就会变为全局变量。
def info():
global str
str = 'hello,world'
print("函数内访问变量 str:", str) # 函数内访问变量 str: hello,world
info()
print("函数为访问 str:", str) # 函数为访问 str: hello,world
globals() 函数为 Python 的内置函数,它可以返回一个包含全局范围内所有变量的字典,该字典中的每个键值对,键为变量名,值为该变量的值。
locals() 函数也是 Python 内置函数之一,通过调用该函数,我们可以得到一个包含当前作用域内所有变量的字典。
这里所谓的“当前作用域”指的是,在函数内部调用 locals() 函数,会获得包含所有局部变量的字典;
而在全局范文内调用 locals() 函数,其功能和 globals() 函数相同。
vars() 函数也是 Python 内置函数,其功能是返回一个指定 object 对象范围内所有变量组成的字典。如果不传入object 参数,vars() 和 locals() 的作用完全相同。
如果所在函数没有返回局部函数,则局部函数的可用范围仅限于所在函数内部;反之,如果所在函数将局部函数作为返回值,则局部函数的作用域就会扩大,既可以在所在函数内部使用,也可以在所在函数的作用域中使用。
闭包,又称闭包函数或者闭合函数。可以提高程序的运行效率。
闭包中外部函数返回的不是一个具体的值,而是一个函数。
closure 属性记录着自由变量的地址。
# 闭包函数
def xx(num1):
def yy(num2):
return num2 ** num1
return yy
sum01 = xx(2)
print(sum01(3)) # 9
print(sum01(4)) # 16
lambda 表达式,又称匿名函数,常用来表示内部仅包含 1 行表达式的函数。
语法:
name = lambda [list] : 表达式
# 求两个数的和,原始函数:
def sum(x, y):
return x + y
print(sum(2, 3)) # 5
# lambda 表达式:
sum = lambda x, y : x + y
print(sum(4, 5)) # 9
lambda 表达式,就是简单函数的简写版本。
区别在于,eval() 执行完会返回结果,而 exec() 执行完不返回结果。
= 1
exec("a = 2") #相当于直接执行 a=2
print(a) # 2
a = exec("2+3") #相当于直接执行 2+3,但是并没有返回值,a 应为 None
print(a) # None
a = eval('2+3') #执行 2+3,并把结果返回给 a
print(a) # 5
# 第一种,导入整个模块
import learn05
# 第二种,导入特定函数
from learn05 import test04
test04.play_games()
from learn05 import test04 as t4
t4.play_games()
import learn05 as l5
from learn05 import *