函数相关知识点
- 函数定义
- 函数参数
- 函数作用域
- 函数属性
1. 函数定义
定义函数,也就是创建一个函数,可以理解为创建一个具有某些用途的工具。定义函数需要用 def 关键字实现。
1.1语法格式
def 函数名(参数列表):
//实现特定功能的多行代码
[return [返回值]]
1.2 参数的含义
函数名:其实就是一个符合 Python 语法的标识符,但不建议读者使用 a、b、c 这类简单的标识符作为函数名,函数名最好能够体现出该函数的功能(如上面的 my_len,即表示我们自定义的 len() 函数)。
形参列表:设置该函数可以接收多少个参数,多个参数之间用逗号( , )分隔。
[return [返回值] ]:整体作为函数的可选参参数,用于设置该函数的返回值。也就是说,一个函数,可以用返回值,也可以没有返回值,是否需要根据实际情况而定。
1.3 注意事项
在创建函数时,即使函数不需要参数,也必须保留一对空的“()”,否则 Python 解释器将提示“invaild syntax”错误。另外,如果想定义一个没有任何功能的空函数,可以使用 pass 语句作为占位符。
1.4 实例
#定义个空函数,没有实际意义
def pass_dis():
pass
#定义一个比较字符串大小的函数
def str_max(str1,str2):
str = str1 if str1 > str2 else str2
return str
# 虽然 Python 语言允许定义个空函数,但空函数本身并没有实际意义。
# 函数中的 return 语句可以直接返回一个表达式的值
def str_max(str1,str2):
return str1 if str1 > str2 else str2
2. 函数参数
2.1 必选参数
# 必选参数:顾名思义,就是函数必须有的入参;
2.2 默认参数
# 默认参数:在函数定义时给定一个初始值,在函数调用时可以不传这个参数,采用默认参数的值;下例中的y就是默认参数;
def add(x,y=5):
sum = x + y
return sum
# 注意:设置默认参数时,必选参数在前,默认参数在后!
2.3 可选参数
# 可选参数:顾名思义,函数参数的个数是可变的,例如下面的numbers就是可变参数。
def calc(*numbers):
sum = 0
for n in numbers:
sum = sum + n * n
return sum
2.4 关键字参数
# 关键字参数:可选参数允许你传入0个或任意个参数,这些可变参数在函数调用时自动组装为一个tuple。而关键字参数允许你传入0个或任意个含参数名的参数,这些关键字参数在函数内部自动组装为一个dict。
def person(name, age, **kw):
print('name:', name, 'age:', age, 'other:', kw)
# 函数person除了必选参数name和age外,还接受关键字参数kw。在调用该函数时,可以只传入必选参数:
person('Michael', 30)
name: Michael age: 30 other: {}
# 也可以传入任意个数的关键字参数:
person('Bob', 35, city='Beijing')
name: Bob age: 35 other: {'city': 'Beijing'}
person('Adam', 45, gender='M', job='Engineer')
name: Adam age: 45 other: {'gender': 'M', 'job': 'Engineer'}
2.5 总结
函数参数的用法是非常灵活的,既可以简单调用,也可以传入复杂的参数。
默认参数一定要用不可变对象,如果是可变对象,程序运行时会有逻辑错误!
要注意定义可变参数和关键字参数的语法:
*args是可变参数,args接收的是一个tuple;
**kw是关键字参数,kw接收的是一个dict。
3. 函数作用域
作用域指的是变量的有效范围
通常,函数内部的变量无法被函数外部访问,但内部可以访问;类内部的变量无法被外部访问,但类的内部可以。通俗来讲,就是内部代码可以访问外部变量,而外部代码通常无法访问内部变量。
3.1 作用域
L (Local) 局部作用域
E (Enclosing) 闭包函数外的函数中
G (Global) 全局作用域
B (Built-in) 内建作用域
3.2 全局变量和局部变量
定义在函数内部的变量拥有一个局部作用域,被叫做局部变量
定义在函数外的拥有全局作用域的变量,被称为全局变量。(类、模块等同理)
# 所谓的局部变量是相对的。局部变量也有可能是更小范围内的变量的外部变量。
# 实例
a = 1 # 全局变量
def func():
b = 2 # 局部变量
print(a) # 可访问全局变量a,无法访问它内部的c
def inner():
c = 3 # 更局部的变量
print(a) # 可以访问全局变量a
print(b) # b对于inner函数来说,就是外部变量
print(c)
3.3 global和nonlocal关键字
global:指定当前变量使用外部的全局变量
nonlocal关键字,它可以修改嵌套作用域(enclosing 作用域,外层非全局作用域)中的变量。
# 举例
a = 1
print("函数outer调用之前全局变量a的内存地址: ", id(a))
def outer():
a = 2
print("函数outer调用之时闭包外部的变量a的内存地址: ", id(a))
def inner():
global a # 注意这行
a = 3
print("函数inner调用之后闭包内部变量a的内存地址: ", id(a))
inner()
print("函数inner调用之后,闭包外部的变量a的内存地址: ", id(a))
outer()
print("函数outer执行完毕,全局变量a的内存地址: ", id(a))
# 运行结果如下,很明显,global使用的是全局变量a。
函数outer调用之前全局变量a的内存地址: 494384192
函数outer调用之时闭包外部的变量a的内存地址: 494384224
函数inner调用之后闭包内部变量a的内存地址: 494384256
函数inner调用之后,闭包外部的变量a的内存地址: 494384224
函数outer执行完毕,全局变量a的内存地址: 494384256
# 将global a改成nonlocal a(可以看到我们真的引用了outer函数的a变量)
函数outer调用之前全局变量a的内存地址: 497726528
函数outer调用之时闭包外部的变量a的内存地址: 497726560
函数inner调用之后闭包内部变量a的内存地址: 497726592
函数inner调用之后,闭包外部的变量a的内存地址: 497726592
函数outer执行完毕,全局变量a的内存地址: 497726528
4. 函数属性
python中的函数是一种对象,它有属于对象的属性。除此之外,函数还可以自定义自己的属性。注意,属性是和对象相关的,和作用域无关。
4.1 自定义属性
# 自定义函数自己的属性方式很简单。假设函数名称为myfunc,那么为这个函数添加一个属性var1:
myfunc.var1="abc"
那么这个属性var1就像是全局变量一样被访问、修改。但它并不是全局变量。
# 可以跨模块自定义函数的属性。例如,在b.py中有一个函数b_func(),然后在a.py中导入这个b.py模块,可以直接在a.py中设置并访问来自b.py中的b_func()的属性。
import b
b.b_func.var1="hello"
print(b.b_func.var1) # 输出hello
4.2 查看函数对象属性
# python函数是一种对象,是对象就会有对象的属性。可以通过如下方式查看函数对象的属性:
dir(func_name)
4.3 实例
def eat(food, drink, sex='男'):
"""
这里描述这个函数是做什么的.例如这函数eat就是吃
:param food: food这个参数是什么意思
:param drink: drink这个参数是什么意思
:return: 执行完这个函数想要返回给调用者什么东西
"""
print(food, drink,sex)
return 666
eat('麻辣烫','肯德基')
# print(dir(eat)) dir() 获取函数所有的属性
['__annotations__', '__call__', '__class__', '__closure__', '__code__',
'__defaults__', '__delattr__', '__dict__', '__dir__', '__doc__',
'__eq__', '__format__', '__ge__', '__get__', '__getattribute__',
'__globals__', '__gt__', '__hash__', '__init__', '__init_subclass__',
'__kwdefaults__', '__le__', '__lt__', '__module__',
'__name__', '__ne__', '__new__', '__qualname__', '__reduce__',
'__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__',
'__subclasshook__']
# 常用的属性
print(eat.__doc__) # str类型 获取函数的注释信息
print(eat.__name__) # str类型 获取函数名
print(eat.__defaults__) # tuple类型 获取默认参数的默认值
print(eat.__closure__) # 与闭包函数相关,后面会涉及