python基础课程系列(补充3)

三、函数
1.如何避开变量作用域的陷阱
1)全局变量与局部变量
======================================================
>>> x = 100
>>> def func():
    print('Inside func:x is {}'.format(x))

>>> func()
Inside func:x is 100
>>> print('x is still:{}'.format(x))
x is still:100
======================================================
这个比较好理解x是全局变量,作用域是整个文件,函数内部是可以引用的.
======================================================
>>> x1 = 100
>>> def func():
    x1 = 10
    print('Changed local x to :{}'.format(x1))
    
>>> func()
Changed local x to :10
>>> print('x1 is still:{}'.format(x1))
x1 is still:100
======================================================
大家看在函数外部有一个变量x1,在函数内部也有一个变量x1,这两个变量虽然名字长的一样,但是是完全不同的:
1.1.函数内部的是本地变量,它的生命周期只在函数内部,出了函数就结束了
1.2.而x1在函数外部模块文件中声明的(python一个文件也叫一个模块),是全局变量,不会被函数里面的局部变量影响,所以最后print的x1还是100

2)全局变量声明
======================================================
>>> x = 100
>>> def func():
    global x #注意加了一个global关键字,表示x是全局作用域
    print('x is:{}'.format(x))
    x = 10
    print('Changed local x to:{}'.format(x))

    
>>> func()
x is:100
Changed local x to:10
>>> print('Value of x:{}'.format(x))
Value of x:10
======================================================
这个函数内部多了一个global关键字,结果就差很多:
2.1.原因在于x被声明为函数内的全局变量,通过global这个语句是自己明确地映射到了模块的作用域
2.2.函数内对x重新赋值x=10,会改变函数外x的值,所以最后print x是10

全局变量简单说就是这3点:
@全局变量是位于模块文件内部的顶层的变量名
@全局变量如何是在函数内被改变的话,一定要用global
@全局变量名在函数内部不经过声明也可以被引用

3)函数内的变量解析原则
python的搜索顺序是:
@先是在函数内部的本地作用域(L)  
@然后是在上一层的函数的本地作用域(E)
@然后是全局作用域(G)
@最后是内置作用域(B)
简单说就是从局部到中央,好比你找一个人,村里找不到找乡->乡里找不到找市里->市里找不到找到全国档案局

3.1.本地函数
在函数内部(def或者lambda)通过任何方式赋值的,而且没有在该函数内声明为全局变量的变量名

3.2.上层函数的本地作用域
python函数是支持嵌套,而且多层嵌套,当你在最里层的函数找不到这个变量的时候,会往上一层的函数找,一层一层由内往外找
======================================================
>>> def f1():
    x = 100
    def f2():
        print(x)
    f2()

    
>>> print(f1())
100
None
======================================================
#因为f2()打印了之后没有return,对没有return的函数就默认返回None
@def定义了一个f1()函数,里面又嵌套了一个f2()函数,这个def生成了一个函数并将其赋值给变量名f2
@f2是f1的本地作用域内的一个本地变量,可以把f2看做一个临时函数,仅仅在f1内部执行的过程中存在.
@f2函数干了一件事打印x,当在f2()内部找不到的时候,就通过LEGB法则往上找,f1()里面找到了x.

3.3.全局(模块)
在模块文件的顶层赋值的变量名,或者在该文件中的def生成的名为全局变量的变量名(函数内global声明的变量)

3.4.内置的作用域

2.函数参数传递
Python里面对函数参数传递分以下几种:
@位置参数
@默认参数  #在函数运行前参数就被赋了值
@关键字参数 #通过变量名字进行匹配,而不是通过位置
@可变长度参数
  1)任意多个非关键字可变长参数(元组)
  2)任意多个关键字变量参数(字典)

1)位置参数
python中最普通的函数使用是这种带位置参数的函数,这跟我们其他语言的普通的函数是一样的,所有参数在传递的时候按照位置来传递
======================================================
>>> def printMessage(message, times):
    print(message * times)
    
>>> printMessage('Hi', 2)
HiHi
======================================================

2)默认参数
======================================================
>>> def printMessage(message, times=3):
    print(message * times)

    
>>> printMessage('python')
pythonpythonpython
======================================================

3)关键字参数
在调用函数的时候,我们希望传递的参数不是僵硬的通过位置来传递,能够有一定的灵活性,能通过变量名进行匹配
======================================================
>>> def func(a, b=10, c=20):
    print('a is: ', a, 'and b is: ', b, 'and c is: ', c)
    
>>> func(3,7)    #没有关键字,就用默认的位置传递
a is:  3 and b is:  7 and c is:  20
>>> func(25, c=24)    #可以跳过b直接到c的赋值
a is:  25 and b is:  10 and c is:  24
>>> func(c=50, a=100)    #使用关键字赋值,无需注意顺序
a is:  100 and b is:  10 and c is:  50
======================================================

4)任意多个位置参数的函数
我们在参数values前面加*,变成(msg,*values),表示只有第一个参数的msg是调用者必须要指定的,该参数后面,可以跟任意数量的位置参数
======================================================
>>> def printScore(msg, *values):
    if not values:
        print(msg)
    else:
        values_str = ','.join(str(x) for x in values)
        print('{},{}'.format(msg,values_str))

        
>>> print('My scores are')
My scores are
>>> print('My scores are', 100, 90, 80)
My scores are 100 90 80
======================================================
一下把100,90,80都打印出来呢,是怎么做到的,是因为python会自动把*操作符后面的形参变成元组传给函数.

5)任意多个关键字形式的参数
如何能接受任意数量的关键字参数,是用**双星号操作符来表示
======================================================
>>> def printLog(msg, **theRest):
    if not theRest:
        print(msg)
    else:
        for key,value in theRest.items():
            print('{},{}={}'.format(msg,key,value))

            
>>> printLog('Log info', version='1.0', platfrom='win')
Log info,version=1.0
Log info,platfrom=win
======================================================
其实就是把**后面的变量参数,按照字典来处理,传递给函数.

综合例子:
包含了关键字参数,默认参数,可变任意数量参数
======================================================
def total(initial=5, *numbers, **keywords):
    count = initial
    for number in numbers:
        count += number

    for key in keywords:
        count += keywords.get(key)

    return count
======================================================
>>> total(10, 1, 2, 3, apple=50, orange=100)
166
 

猜你喜欢

转载自blog.csdn.net/zhaocen_1230/article/details/81772008