函数

函数:由语句块(若干语句组成),函数名称,参数构成,是组织代码的最小单元,用来完成某种功能;

函数的作用:封装代码,复用,减少冗余代码,使代码更加简洁美观,可读性更高,易懂;

函数的定义:
def    函数名(参数列表):	
       函数体(代码块)
       [return 返回值]

def    add(x,y):	      
       result = x+y      
       return result
out = add(4,5)
               print(out)

add是函数名,即标识符,add()调用函数;

python的函数如果过没有指定return语句,默认返回值是None;

return语句不一定是函数块的最后一条语句,一个函数可以有多条return语句,但是只有一条会执行,函数执行了return语句以后,后面的语句块就不会执行了;

上面函数定义中的参数x,y只是形式参数,函数调用是的4,5才是实际参数;

函数是一个可调用对象,canllable()判断是否为可调用对象,返回一个布尔值;

函数参数:

参数调用时传入的参数要和定义时参数的个数相匹配(可变参数除外);

参数列表一般顺序是:普通参数,缺省参数,可变位置参数,keyword-only参数,可变关键字参数;

位置参数:

定义def add(x,y,z):

调用add(1,2,3)

实参和形参一一对应,数量必须相同;

关键字参数:

定义def add(x,y,z):

调用add(x=1,y=2,z=3)

关键字传参时,x,y,z顺序可以和形参顺序不同,参数个数必须相同;

位置参数和关键字参数混用是,位置参数必须放在关键字参数之前传入;

可变参数:

定义def add(*args):

调用add(3,6,9)

可变位置参数一般用*args表示,可变位置参数收集到的实参整合成一个tuple;

定义def add(**kwargs):

调用add(a=3,b=6,c=9)

可变关键字参数一般用**kwargs表示,可变关键字参数收集到的实参整合成一个dict;

参数解构:

def add(x, y):  
    return x+y
add(*(4,5)) 
add(*[4,5]) 
add(*{4,6})
d = {'x': 5, 'y': 6}
add(**d)
add(**{'a': 5, 'b': 6})

非字典类型使用*,字典类型使用**;

解构出的元素数目要和参数数目和类型相匹配;

函数参数默认值:
定义函数的时候给参数一个默认值:
def login(host='127.0.0.1',port='8080',username='LPL',password='s7win'):
  print('{}:{}@{}/{}'.format(host, port, username, password))
login()
作用:参数默认值可以在为未传入足够实参的时候,对给定的参数取默认值;参数非常多的时候,一些不需要用户经常输入或修改的参数,简化函数调用;

函数作用域***

全局作用域:在整个程序运行环境中可见;

全局变量global(能不用则不用)

x = 2
def foo():      
    global x      
    x += 1     
    return x
foo()
print(foo())

使用global关键字,将函数foo内的x变量声明为外部全局作用域中定义的x变量,全局作用域中必须有定义x变量,不然会抛异常;

局部作用域:在函数内部可见,局部变量使用范围不能超过其所在的局部作用域;

在嵌套函数中,外层局部作用域中的变量在内层局部作用域中是可见的,内层局部作用域中的变量在外层局部变量中是不可见的,内层局部作用域中如果有和外层局部作用域中相同的变量,相当于在内部重新定义一个新的变量,和外层局部作用域无关;

def outer1(): 					                     		
    o = 65							         
    def inner():							 
        print("inner {}".format(o))				 	    
        print(chr(o))						 	     
    print("outer {}".format(o))						     
    inner()								 								       
outer1()

def outer2():
    o = 65
    def inner():
        o = 97
        print("inner {}".format(o))
        print("chr(o)")
    print("outer{}".format(o))
    inner()
outer2()							   

闭包*

出现在嵌套函数中,内层函数引用到外层函数的自由变量就是闭包;

自由变量:未在本地作用域中定义的变量,不能是全局作用域变量;

def counter():
  c = [0]
  def inc():
    c [0] += 1
    return c[0]
  return inc()
foo = counter()
print(foo,foo)
c = 100
print(foo)
print(c)

执行结果:
1 1
1
100

使用nonlocal关键字,将变量标记为不在本地作用域定义,而在某上层的局部作用域中定义的变量(不能是在全局作用域中定义的变量);

def counter():
  c = 0
  def inc():
    nonlocal c
    c += 1
    return c
  return inc()
foo = counter()
print(foo)

默认作用域:

python函数参数的默认值放在了属性中,这个属性就伴随这个函数对象的整个生命周期(__defaults__使用元组保存默认值,__kwdefaults__使用字典保存所有的keyword-only默认值);

def foo(xyz=[], u='abc', z=123):
  xyz.append(1)
  return xyz
print(foo(), id(foo))
print(foo.__defaults__)
print(foo(), id(foo))
print(foo.__defaults__)
执行结果:
[1] 30359064
([1], 'abc', 123)
[1, 1] 30359064
([1, 1], 'abc', 123)

#函数对象没有变,这里xyz=[]是个引用类型,所以__defaults__默认值会改变;

def foo(xyz=[], u='abc', z=123):
  xyz = xyz[:] 
  xyz.append(1)
  print(xyz)
foo()
print(foo.__defaults__)
foo()
print(foo.__defaults__)
foo([10])
print(foo.__defaults__)
foo([10,5])
print(foo.__defaults__)
执行结果:[1]
([], 'abc', 123)
[1]
([], 'abc', 123)
[10, 1]
([], 'abc', 123)
[10, 5, 1]
([], 'abc', 123)

#函数体内,xyz=xyz[:]传入参数或者默认参数的cp,不能修改__defaults__默认值;

def foo(xyz=None, u='abc', z=123):
  if xyz is None:
    xyz = []
  xyz.append(1)
  print(xyz)
foo()
print(foo.__defaults__)
foo()
print(foo.__defaults__)
foo([10])
print(foo.__defaults__)
foo([10,5])
print(foo.__defaults__)
执行结果:
[1]
(None, 'abc', 123)
[1]
(None, 'abc', 123)
[10, 1]
(None, 'abc', 123)
[10, 5, 1]
(None, 'abc', 123)

#使用不可变类型默认值,如果使用缺省值None就创建一个列表,如果传入一个列表,就修改这个列表;

原文地址:https://www.cnblogs.com/52py/p/7664908.html