为什么要用函数
python的函数是由一个新的语句编写,即def ,def是可执行的语句--函数并不存在,知道python运行了def后才存在。
函数是通过赋值函数传递的,参数通过赋值传递给函数。
def语句将会创建一个函数对象并将其赋值给一个函数名,def语句的一般格式如下:
def function_name(arg1,arg2[....]):
statement
[return value]
返回值不是必须的,如果没有return语句,则python默认返回None
函数命名规则:
函数名必须以下花心或字母开头,可以包含任意字母、数字和下划线的组合。不能使用任何标点符号;
函数名是区分大小写的。
函数名不能是关键字
函数定义
def 关键词开头,空格之后接函数名称和圆括号(),最后还有一个":"。
def 是固定的,不能变,必须是连续的def三个字母,不能分开。。。它们要相亲相爱的在一起。
空格 为了将def关键字和函数名分开,必须空(四声),当然你可以空2格、3格或者你想空多少都行,但正常人还是空1格。
函数名:函数名只能包含字符串、下划线和数字且不能以数字开头。虽然函数名可以随便起,但我们给函数起名字还是要尽量简短,并能表达函数功能
括号:是必须加的!
注释:每一个函数都应该对功能和参数进行相应的说明,应该写在函数下面第一行。以增强代码的可读性。
函数的返回值
关键字:return
#runturn的作用:
#结束函数的执行
#返回要返回的值
#返回值得两种情况
1)返回值为None
2)返回值不为None
- 返回一个值
- 返回多个值
函数调用--接收返回值
1)返回值为None
2)返回值不为None
- 返回一个值 用一个变量接收
- 返回多个值
- 用一个变量接收为元组数据形式
- 用等于返回值数的变量接收
参数
定义的角度:
- 位置参数
- 默认参数
- 动态参数
- *args 位置传参,元组形式传参
- **kwargs ,关键字传参
参数接收顺序
- 位置参数
- *args 默认参数 元组 (1,2)
- **kwargs 动态参数 字典 {a:1,b:2}
调用函数角度:
- 位置参数
- 关键字传参 func(1,2)
- 动态参数 *tup **dic func(a = 1,b = 2)
装饰器:
由于函数也是一个对象,而且函数对象可以赋值给变量,所以通过变量也能调用该函数
def now():
print('hello world')
f= now
f()
print(now.__name__) # 输出 now
print(f.__name___) # 输出 now
现在,假设我们要增强now()
函数的功能,比如,在函数调用前后自动打印日志,但又不希望修改now()
函数的定义,这种在代码运行期间动态增加功能的方式,称之为“装饰器”(Decorator)。
def log(func):
def wrapper(*args, **kw):
print('call %s():' % func.__name__)
return func(*args, **kw)
return wrapper
观察上面的log
,因为它是一个decorator,所以接受一个函数作为参数,并返回一个函数。我们要借助Python的@语法,把decorator置于函数的定义处:
@log
def now():
print('hello')
把@log
放到now()
函数的定义处,相当于执行了语句:
now = log(now)
由于log()
是一个decorator,返回一个函数,所以,原来的now()
函数仍然存在,只是现在同名的now
变量指向了新的函数,于是调用now()
将执行新函数,即在log()
函数中返回的wrapper()
函数。
wrapper()
函数的参数定义是(*args, **kw)
,因此,wrapper()
函数可以接受任意参数的调用。在wrapper()
函数内,首先打印日志,再紧接着调用原始函数。
如果decorator本身需要传入参数,那就需要编写一个返回decorator的高阶函数,写出来会更复杂。比如,要自定义log的文本:
def outer(text):
def decorator(func):
def wrapper(*args, **kw):
print('%s %s():' % (text, func.__name__))
return func(*args, **kw)
return wrapper
return decorator
这个3层嵌套的decorator用法如下:
@outer('execute')
def now():
print('hello')
now()
执行结果如下:
execute now()
hello
和两层嵌套的decorator相比,3层嵌套的效果是这样的:
now = outer('execute')(now)
一个函数调用多个装饰器
@outer('execute')
@log
def now():
print('hello')
执行结果如下:
execute wrapper():
call now():
hello
两个装饰器的效果是这样的:
now = outer('execute')(log(now))
now()
或者
now = log(now)
now = outer('execute')(now)
now()