函数定义
关键字def用于创建用户自定义函数,函数定义就是一些可执行的语句。
def square(x): return x**2
函数调用参数
1. 默认参数值:这允许用户为函数的参数定义一些默认值。
def show_args(arg, def_arg=1, def_arg2=2): return "arg={}, def_arg={}, def_arg2={}".format(arg, def_arg, def_arg2)
上面例子函数的定义中,包含一个正常位置的参数arg和两个默认参数def_arg和def_arg2。该函数可以以下面中的任何一种方式进行调用:
(1)只提供非缺省位置参数值。在本例中,缺省参数取默认值:
def show_args(arg, def_arg=1, def_arg2=2): return "arg={}, def_arg={}, def_arg2={}".format(arg, def_arg, def_arg2) >>> show_args("tranquility") 'arg=tranquility, def_arg=1, def_arg2=2'
(2)用提供的值覆盖一些默认的参数值,包括非缺省位置参数:
def show_args(arg, def_arg=1, def_arg2=2): return "arg={}, def_arg={}, def_arg2={}".format(arg, def_arg, def_arg2) >>> show_args("tranquility", "to Houston") 'arg=tranquility, def_arg=to Houston, def_arg2=2'
(3)为所有参数提供值,可以用这些值覆盖默认参数值:
def show_args(arg, def_arg=1, def_arg2=2): return "arg={}, def_arg={}, def_arg2={}".format(arg, def_arg, def_arg2) >>> show_args("tranquility", "to Houston", "the eagle has landed") 'arg=tranquility, def_arg=to Houston, def_arg2=the eagle has landed'
2. 关键字参数:以“kwarg=value”的形式使用关键字参数也可以调用函数。其中,kwarg指函数定义中使用的参数名称。以下面定义的含有默认和非默认参数的函数为例:
def show_args(arg, def_arg=1): return "arg={}, def_arg={}".format(arg, def_arg)
为了演示使用关键字参数调用函数,下面的函数可以以后面的任何一种方式调用:
show_args(arg="test", def_arg=3) show_args(test) show_args(arg="test") show_args("test", 3)
在函数调用中,关键字参数不得早于非关键字参数,所以调用会失败
3. 任意的参数列表:Python还支持定义这样的函数,该函数可以接受以元组形式传递的任意数量的参数,Python教程中的一个例子如下所示:
def write_multiple_items(file, separator, *args): file.write(separator.join(args))
任意数量的参数必须在正常参数之后。在本例中,任意数量参数存在于参数file和separator之后。下面是一个调用上述定义函数的示例:
f = open("test.txt", "wb") write_multiple_items(f, " ", "one", "two", "three", "four", "five")
命名空间一共分为三种:
全局命名空间
局部命名空间
内置命名空间
*内置命名空间中存放了python解释器为我们提供的名字:input,print,str,list,tuple...它们都是我们熟悉的,拿过来就可以用的方法。
三种命名空间之间的加载与取值顺序:
加载顺序:内置命名空间(程序运行前加载)->全局命名空间(程序运行中:从上到下加载)->局部命名空间(程序运行中:调用时才加载)
取值:
x = 1 def f(x): print(x) print(10)
在全局调用:全局命名空间->内置命名空间
x = 1 def f(x): print(x) f(10) print(x)
print(max)
作用域
作用域就是作用范围,按照生效范围可以分为全局作用域和局部作用域。
全局作用域:包含内置名称空间、全局名称空间,在整个文件的任意位置都能被引用、全局有效
局部作用域:局部名称空间,只能在局部范围内生效
函数名的本质
函数名本质:就是函数的内存地址
闭包函数:
内部函数包含对外部作用域而非全剧作用域名字的引用,该内部函数称为闭包函数
#函数内部定义的函数称为内部函数
闭包:内部函数包含对外部作用域而非全剧作用域名字的引用,该内部函数称为闭包函数
装饰器的形成过程
import time def func1(): print('in func1') def timer(func): def inner(): start = time.time() func() print(time.time() - start) return inner func1 = timer(func1) func1() 装饰器——简单版1
import time def timer(func): def inner(): start = time.time() func() print(time.time() - start) return inner @timer #==> func1 = timer(func1) def func1(): print('in func1') func1() 装饰器——语法糖
装饰器的本质:一个闭包函数
装饰器的功能:在不修改原函数及其调用方式的情况下对原函数功能进行扩展
开放封闭原则
1.对扩展是开放的
为什么要对扩展开放呢?
我们说,任何一个程序,不可能在设计之初就已经想好了所有的功能并且未来不做任何更新和修改。所以我们必须允许代码扩展、添加新功能。
2.对修改是封闭的
为什么要对修改封闭呢?
就像我们刚刚提到的,因为我们写的一个函数,很有可能已经交付给其他人使用了,如果这个时候我们对其进行了修改,很有可能影响其他已经在使用该函数的用户。
装饰器完美的遵循了这个开放封闭原则。
def timer(func): def inner(*args,**kwargs): '''执行函数之前要做的''' re = func(*args,**kwargs) '''执行函数之后要做的''' return re return inner
带参数的装饰器
def outer(flag): def timer(func): def inner(*args,**kwargs): if flag: print('''执行函数之前要做的''') re = func(*args,**kwargs) if flag: print('''执行函数之后要做的''') return re return inner return timer @outer(False) def func(): print(111) func() 带参数的装饰器
多个装饰器装饰同一个函数
def wrapper1(func): def inner(): print('wrapper1 ,before func') func() print('wrapper1 ,after func') return inner def wrapper2(func): def inner(): print('wrapper2 ,before func') func() print('wrapper2 ,after func') return inner @wrapper2 @wrapper1 def f(): print('in f') f() 多个装饰器装饰同一个函数