5.1 Python 函数-默认参数,*args,**kwargs的使用;作用域-局部空间使用全局变量需要注意的事项等

Python 函数

转载请标明出处(http://blog.youkuaiyun.com/lis_12/article/details/52815944).

1 函数

  1. 格式:

    def add(x,y):

    ​ return x+y

  2. 参数的顺序和数量必须与函数定义匹配,否则会引发TypeError.可以为函数设置默认参数,如果函数中存在默认参数,该参数以及后续参数都是可选的.(显式传参没必要按顺序赋值);

  3. 定义函数后,默认的参数值会传递给以值的方式提供给默认对象,例如:

    a = 1
    def f(x = a):
       print 'a:',a,'x:',x
    f()  #a: 1 x: 1
    a = 2
    f()  #a: 2 x: 1

    使用可变对象作为默认值可能会发生意料之外的行为.

    def f(x = []):
       x.append(1)
       print x
    f()#[1]
    f()#[1,1]

    如果不理解上述结果,参见(http://blog.youkuaiyun.com/lis_12/article/details/52693333)

函数传参

一般格式:函数中参数顺序为fun(一般参数,默认参数,元组(*),字典(**))

  1. 函数中参数传递的是引用;

  2. *arg,给参数中加上*后,函数就可以接受任意数量的参数(这也是Python不需要重载的原因);

  3. 可以显式地给每一个参数赋值,此时就不需要按顺序赋值;

  4. 函数中以**arg开头的参数,可以把所有额外的关键字参数(不在函数参数中)都放入字典中;

  5. 如果函数有多个参数,可以使用*arg来传参,如函数fun(a,b,c,d,e),arg = [0,1,2,3,4],fun(*arg)等价于fun(0,1,2,3,4,5);

  6. def fun(arg1,arg2=0,*arg_tuple,**arg_dict):
       '''函数说明'''
       print 'arg1:',arg1
       print 'arg2:',arg2
       print 'arg_tuple:',arg_tuple
       print 'arg_dict:',arg_dict
    
    def fun0(a,b,c):
       print a,b,c
    
    if __name__ == '__main__':#主程序
       '''如果模块是被导入的 __name__为文件名字,如果是直接执行的,__name__ 为__main__'''
       fun(1)                            #1,0,[],{}
       fun(1,2)                          #1,0,[],{}
       fun(1,2,3)                        #1,2,[3],{}
       fun(1,2,3,4,5)                    #1,2,[3,4,5],{}
       fun(1,*(2,3,4,5))                 #1,2,[3,4,5],{},等价于fun(1,2,*(3,4,5)) 
       fun(1,2,*(3,4,5))                 #1,2,[3,4,5],{}
    
       #这两个是不一样的,tuple处不同
       fun(1,2,*(3,4,5),**{'x':1,'y':2}) #将(3,4,5)当成了三个参数1,2,[3,4,5],{'y': 2, 'x': 1}
       fun(1,2,(3,4,5),**{'x':1,'y':2})  #(3,4,5)为一个参数1,2,((3,4,5),),{'y': 2, 'x': 1}
    
       fun0(c=1,b=2,a=3) #3  2   1
       fun0(*(1,2,3))    #1,2,3  等价于fun0(1,2,3)

注:当元组中只有一个元素时候,需要在后面加上,号,如果不加这个’,’,就会将()按小括号处理.

作用域

  1. 每次执行一个函数的时候,都会创建一个新的局部命名空间.该空间代表一个局部环境,其中包含函数参数的名称和函数体内赋值的变量.

  2. 解析变量时,解释器将首先搜索局部命名空间,如果没有找到匹配的名称,就会搜索全局命名空间,如果仍未找到,则会检查内置命名空间,还找不到的话就会引发异常.

    a = 1
    def f():
       a = 12   #函数中的a并不是全局变量中的a,而是新建的局部变量a.
    f()
    print a      #1
    
    
    #改变上述行为
    
    a = 1
    def f():
       global a #将a声明为属于全局命名空间的全局变量
       a = 12
    f()
    print a      #12  
  3. 局部作用域可以嵌套,但是函数不能给定义在外部函数中的变量重新赋值,即外部的作用域不能给里面作用域的变量重新赋值,如f1()里就不能给f()里面的变量重新赋值.注:虽然不能重新赋值,但是其他的操作还是能够用的.

    在函数体内使用global声明的变量为全局变量,在全局命名空间内.

    (如果不理解,见图和代码)

    作用域

    a = 1
    def f():
       b = 2
    
       def f1():
           try:
               a = a - 1#a是全局变量,f1()为a的外部作用域,so不能重新赋值
           except Exception,e:
               print e     
           #print a,b  这样会报错,但是不知道原因....
    
       def f2():
           try:
               b -= 1#b是f1()作用域中的变量,f2()为b的外部作用域,so不能重新赋值
           except Exception,e:
               print e
           #print a,b
    
       def f3():
           c = 3
           def f31():
               #print a,b,c
               try:
                   c -= 1#c是f3()作用域中的变量,f31()为c的外部作用域,so不能重新赋值
               except Exception,e:
                   print e        
           f31()
       f1()
       f2()
       f3()
    
    f()
    '''
    result:
    local variable 'a' referenced before assignment
    local variable 'b' referenced before assignment
    local variable 'c' referenced before assignment
    '''
    
    #other
    
    a = []
    def f():
       a.append(1)#只是在原地址上进行了操作,不是重新赋值
       print a
    f()  #[1]

    以f1()为例,语句a = a - 1在给a局部赋值之前会尝试读取它的值,虽然存在全局变量a,但是不会给局部变量a提供值,但是局部空间内没有变量a,所以报错.

    个人理解:当使用赋值操作时,解释器会认为f1()局部作用域内已经创建了一个局部变量a,所以不会使用全局变量a,但是在f1()内并没有创建一个局部变量a.

  4. 函数中的变量在定义时,就确定了它是局部变量还是全局变量,不能中途改变它们的作用域.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值