python函数学习总结

函数是用来组织 可复用的一组功能代码,提高代码利用率,使用def关键字作为函数声明,由若干语句块,函数名称,参数列表组成

函数的作用:函数是对一组功能代码最基本的封装,主要目的是复用,减少代码冗余,代码简洁宜读

 

函数定义:函数名尽量做到见名知意,不能用中文,语句块必须缩进,4个空格或者一个tab(据国外调查敲空格的程序员比敲tab的挣钱多美剧硅谷多次讨论是用空格还是tab)

参数列表:分为形参,位置参数,关键字参数

函数返回值使用return 把计算结果返回,如果函数中无return语句则会隐式调用return返回一个None值

 

In [55]: def fn(x,y):
    ...:     return x+y

  

函数调用:填入实参,返回计算结果,如果函数在定义之前调用会抛出NameError异常,函数是可调用对象,可以用callable()函数检查,函数调用加括号代表返回函数计算结果,不加括号的调用属于函数本身,如果没有return会隐式返回一个None参数。

#函数定义之前调用抛出NameError异常
In [71]: fn(2,3)
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-71-62407a230d5c> in <module>()
----> 1 fn(2,3)

NameError: name 'fn' is not defined

#函数定义
In [63]: def fn(x,y):
    ...:     return x+y
    ...:
#函数调用,并返回结果
In [64]: fn(2,3)
Out[64]: 5
#调用函数不带括号时,函数属于一个变量,调用的是函数本身
In [65]: fn
Out[65]: <function __main__.fn>
#可打印函数在当前python环境的内存地址
In [67]: print(fn)
<function fn at 0x000001EB418080D0>
#函数属于可调用对象
In [66]: callable(fn)
Out[66]: True

  

#函数体无return语句,会返回None,print是输出控制台的不返回计算结果,
In [78]: def fn(x,y):
    ...:     print(x+y)
    ...:

In [79]: xy=fn(2,3)
5
#返回NoneType类型
In [80]: type(xy)
Out[80]: NoneType

  

函数参数:位置参数按照参数定义顺序传入,关键字参数实参也可使用形参名字一一对应的来传递参数那么传参顺序和定义顺序可以不同,位置参数必须在关键字参数之前传入。

 

In [81]: def fn(x,y,z):
    ...:     return x+y+z
    ...:
#使用位置和关键字参数混合
In [82]: fn(1,2,z=10)
Out[82]: 13
#使用位置参数
In [85]: fn(1,2,10)
Out[85]: 13
#使用关键字参数
In [86]: fn(z=1,x=10,y=2)
Out[86]: 13

  

函数默认参数:在形参的后面定一个关键字参数作为默认值,当函数调用的时候没有传入该值的时候就使用默认参数,不需要用户每次输入。

In [87]: def fn(x,y,z=100):
    ...:     return x+y+z
#当值没传够时,使用默认值
In [88]: fn(1,2)
Out[88]: 103
#覆盖默认值
In [89]: fn(1,2,101)
Out[89]: 104
#覆盖默认值
In [90]: fn(1,2,1000)
Out[90]: 1003

  

可变参数:可变位置参数,可变关键字参数,混合使用时优先级:普通位置参数-->可变位置参数-->可变关键字参数

可变位置参数在形参前使用星号*,一般使用*args,函数内部对其用元组收集

可变关键字参数在形参前使用双型号**,一般使用**kwargs,函数内部对其用字典收集

In [6]: def fn(x,y,*args,**kwargs):
   ...:     return '{}:{} {}:{}'.format(type(args),args,type(kwargs),kwargs)
   ...:

In [7]: fn(1,2,[12,3,4],23,5,a=1,b={3,5,62})
Out[7]: "<class 'tuple'>:([12, 3, 4], 23, 5) <class 'dict'>:{'a': 1, 'b': {3, 5, 62}}"

  

 keyword-only参数:如果可变位置参数或者星号参数后出现了普通形参,会转变形参为keyword-only参数

#可变位置参数在前
In [8]: def fn(*args,x):
   ...:     return '{}:{} {}:{}'.format(type(args),args,type(x),x)
   ...:

In [9]: fn(1,2,[12,3,4],23)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-9-0440b5f38ecc> in <module>()
----> 1 fn(1,2,[12,3,4],23)

TypeError: fn() missing 1 required keyword-only argument: 'x'

In [10]: fn(1,2,[12,3,4],x=23)
Out[10]: "<class 'tuple'>:(1, 2, [12, 3, 4]) <class 'int'>:23"

#星号在前
In [11]: def fn(*,x,y):
    ...:     return '{}:{} {}'.format(type(x),x,type(y))
    ...:

In [12]: fn(2,3)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-12-62407a230d5c> in <module>()
----> 1 fn(2,3)

TypeError: fn() takes 0 positional arguments but 2 were given

In [13]: fn(2,y=3)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-13-6c4c8b96773e> in <module>()
----> 1 fn(2,y=3)

TypeError: fn() takes 0 positional arguments but 1 positional argument (and 1 keyword-only argument) were given

In [14]: fn(x=2,y=3)
Out[14]: "<class 'int'>:2 <class 'int'>"

  

参数解构:给函数提供参数的时候可以加上 *或者**符号,对传入实参集合解开,字典类型用**进行解封,非字典类型用*进行解封

In [18]: def add(*args):
    ...:     s=0
    ...:     for x in args:
    ...:        s+=x
    ...:     return 'args::{}  s::{}'.format(args,s)
    ...:

In [19]: add(*[1,2,4,2])
Out[19]: 'args::(1, 2, 4, 2)  s::9'

In [20]: add(*range(10))
Out[20]: 'args::(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)  s::45'


In [21]: def add(**kwargs):
    ...:     s=0
    ...:     for x in kwargs.values():
    ...:        s+=x
    ...:     return '{}::{}'.format(kwargs,s)
    ...:

In [22]: add(**{'a':2,'b':3})
Out[22]: "{'a': 2, 'b': 3}::5"

 

return语句:该语句主要使函数返回“函数返回值”并退出该函数,函数都应该有返回值如果没有return语句或者没有执行到函数中的return则会返回None即return None,一个函数可以有多个return语句但仅一个return语句被执行见return语句函数即退出结束函数调用,return可以返回多个值,可以自定义返回值类型

In [1]: def fn():
   ...:     return 'hello'

In [2]: fn()
Out[2]: 'hello'
#函数不定义return语句,会隐式调用return None作为函数返回值
In [3]: def fn():
   ...:     print('hello')
#print函数控制台打印字符
In [4]: fn()
hello

In [5]: f=fn()
hello
#无返回值None但控制台不打印需要借助print函数查看输出值
In [6]: f
In [8]: print(f)
None
#函数为None,print函数主要是在控制台打印你想要的提示信息,并不返回“函数返回值”
In [7]: type(f)
Out[7]: NoneType
#定义两个return语句,只会执行第一个return
In [9]: def fn():
   ...:     return 'hello'
   ...:     return 'hi'
   ...:

In [10]: fn()
Out[10]: 'hello'
#return语句后不跟返回值会返回None
In [12]: def fn():
    ...:     return

In [13]: fn()

In [14]: print(fn())
None

In [15]: type(fn())
Out[15]: NoneType

  

作用域:全局作用域在整个python程序当前运行环境可见,局部作用域在函数,类内部可见,局部作用域变量使用仅限当前作用域可用。

#全局作用域全局可见,内层函数对外层函数的作用域变量可读,但不可修改
In [1]: x=1
In [5]: x=1
   ...: def fn():
   ...:     y=1
   ...:     def iner():
   ...:         z=1
   ...:         return x,y,z
   ...:     return iner(),x,y
   ...:

In [6]: fn()
Out[6]: ((1, 1, 1), 1, 1)
#内层函数仅仅对当前函数作用域的变量有修改权限
In [7]: x=1
   ...: def fn():
   ...:     y=1
   ...:     def iner():
   ...:         z=1
   ...:         x+=1
   ...:         y+=1
   ...:         return x,y,z
   ...:     return iner(),x,y
   ...:

In [8]: fn()
---------------------------------------------------------------------------
UnboundLocalError                         Traceback (most recent call last)
<ipython-input-8-e1d0f67027b9> in <module>()
----> 1 fn()

<ipython-input-7-e3762ad2288c> in fn()
      7         y+=1
      8         return x,y,z
----> 9     return iner(),x,y

<ipython-input-7-e3762ad2288c> in iner()
      4     def iner():
      5         z=1
----> 6         x+=1
      7         y+=1
      8         return x,y,z

UnboundLocalError: local variable 'x' referenced before assignment

#函数定义与外层函数或全局变量相同变量名时,当前函数作用域变量会覆盖其他作用域变量
In [11]: x=1
    ...: def fn():
    ...:     y=1
    ...:     def iner():
    ...:         z=1
    ...:         x=10
    ...:         x+=10
    ...:         y=100
    ...:         return x,y,z
    ...:     return iner(),x,y
    ...:

In [12]: fn()
Out[12]: ((20, 100, 1), 1, 1)

#可以使用global关键字将函数内作用域内的变量声明为全局作用域的变量,global尽量不要使用,使用函数传参可规避
In [13]: x=1
    ...: def fn():
    ...:     y=1
    ...:     def iner():
    ...:         z=1
    ...:         global x
    ...:         x+=10
    ...:         return x,y,z
    ...:     return iner,x,y
    ...:

In [14]: fn()
Out[14]: ((11, 1, 1), 11, 1)

#nonlocal将上层函数作用域的变量非本地作用域中的变量标记为本地可用,该变量不能是全局作用域变量
In [17]: x=1
    ...: def fn():
    ...:     y=1
    ...:     def iner():
    ...:         z=1
    ...:         global x
    ...:         x+=10
    ...:         nonlocal y
    ...:         y+=99
    ...:         return x,y,z
    ...:     return iner(),x,y
    ...:

In [18]: fn()
Out[18]: ((11, 100, 1), 11, 100)

  

变量作用域的查找原则LEGB:LEGB规定了查找一个名称的顺序为:local-->enclosing function locals-->global-->builtin

LEGB含义解释:
L-Local(function);函数内的名字空间
E-Enclosing function locals;外部嵌套函数的名字空间(例如closure)
G-Global(module);函数定义所在模块(文件)的名字空间
B-Builtin(Python);Python内置模块的名字空间

 

函数闭包:在嵌套函数中,内层函数引用到了外层函数的自由变量就形成了闭包,普通的函数嵌套当函数执行完成后立即被回收,但闭包不会,函数引用会一直存在于当前python环境。

In [37]: def fn():
    ...:     y=1
    ...:     def iner():
    ...:         return y+1
    ...:     return iner
#闭包调用方式
In [38]: fn()()
Out[38]: 2

In [39]: f=fn()

In [40]: f()
Out[40]: 2  

 

函数销毁:1.定义了重名函数会覆盖上一个函数;2.使用del语句进行删除;3.整个python解释器退出时

posted @ 2018-05-02 21:48  mictiger  阅读(307)  评论(0)    收藏  举报