python函数

2018-08-24  本文已影响0人  lflish

python函数

def函数定义

def <name>(arg1, arg2,... argN):    
    <statements>
    return <value>

与C这样的编译语言不同,Python函数在程序运行之前并不需要全部定义。更确切地讲,def在运行时才进行评估,而在def之中的代码在函数调用后才会评估。

global语句

它并不是一个类型或大小的声明,它是一个命名空间的声明。它告诉Python函数打算生成一个或多个全局变量名。也就是说,存在于整个模块内部作用域(命名空间)的变量名。

X = 88                   # Global X
def func():    
    global X    
    X = 99               # Global X: outside deffunc()
print(X)                 # Prints 99

y, z = 1, 2              # Global variables in module
def all_global():    
    global x             # Declare globals assigned    
    x = y + z            # No need to declare y, z: LEGB rule

原则

# first.py
X = 99          # This code doesn't know about second.py

# second.py
import first
print(first.X)   # Okay: references a name in another file
first.X = 88     # But changing it can be too subtle and implicit

升级后

# first.py
X = 99
def setX(new):    
    global X    
    X = new
    
# second.py
import first
first.setX(88)

文件模块使用全局变量

# thismod.py
var = 99            # Global variable == module attribute

def local():    
    var = 0                            # Change local var

def glob1():    
    global var                         # Declare global (normal)    
    var += 1                           # Change global var

def glob2():    
    var = 0                            # Change local var    
    import thismod                     # Import myself    
    thismod.var += 1                   # Change global var

def glob3():    
    var = 0                            # Change local var    
    import sys                         # Import system table    
    glob = sys.modules['thismod']      # Get module object (or use __name__)    
    glob.var += 1                      # Change global var

def test():    
    print(var)  #99    
    local(); glob1(); glob2(); glob3()    
    print(var)  #102

嵌套作用域举例

def f1():    
    X = 88   
    def f2():       
        print(X)     # Remembers X in enclosing def scope   
    return f2        # Return f2 but don't call it   
action = f1()        # Make, return function
action()             # Call it now: prints 88

在这个代码中,我们命名为f2的函数的调用动作的运行是在f1运行后发生的。f2记住了在f1中嵌套作用域中的x,尽管f1已经不处于激活状态。有点费解 这都可以。

通常来说,类是一个更好的像这样进行“记忆”的选择,因为它们让状态变得很明确。不使用类的话,全局变量、像这样的嵌套作用域引用以及默认的参数就是Python的函数能够保留状态信息的主要方法了。为

nonlocal语句

nonlocal和global一样,声明了将要在一个嵌套的作用域中修改的名称。和global的不同之处在于,nonlocal应用于一个嵌套的函数的作用域中的一个名称,而不是所有def之外的全局模块作用域;

>>>def tester(start):
...    state = start              # Each call gets its own state
...    def nested(label):
...        nonlocal state         # state必须提前声明 不然会报错
...        print(label, state)
...        state += 1              # Allowed to change it if nonlocal
...    return nested
...
>>>F = tester(0)
>>>F('spam')                       # Increments state on each call
spam 0
>>>F('ham')
ham 1
>>>F('eggs')
eggs 2

函数参数

不可变对象
>>> x = 1
>>> id(x)
19852392
>>> x +=1
>>> id(x)
19852368
不可变对象的函数传参
>>>def f(a):    # a is assigned to (references) passed object
...    a = 99   # Changes local variable a only
...
>>>b = 88
>>>f(b)         # a and b both reference same 88 initially
>>>print(b)     # b is not changed
88
可变对象的函数传参
>>>def changer(a, b):  # Arguments assigned references to objects
...    a = 2          # Changes local name's value only
...    b[0] = 'spam'   # Changes shared object in-place
...
>>>X = 1
>>>L = [1, 2]          # Caller
>>>changer(X, L)       # Pass immutable and mutable objects
>>>X, L                # X is unchanged, L is different!
(1, ['spam', 2])
避免可变参数的修改

方式一

L = [1, 2]
changer(X, L[:])   # Pass a copy, so our 'L' does not change

方式二

def changer(a, b):   
    b = b[:]             # Copy input list so we don't impact caller
    a = 2
    b[0] = 'spam'            # Changes our list copy only

方式三 转换为元组

L = [1, 2]
changer(X, tuple(L))       # Pass a tuple, so changes 

特定的参数匹配模型

关键字参数
>>>def f(a, b, c): print(a, b, c)
#普通调用
>>>f(1, 2, 3)

#关键字参数
>>>f(c=3, b=2, a=1)

#默认参数
>>>def f(a, b=2, c=3): print(a, b, c)
>>>f(1)


#收集参数

>>>def f(*args): print(args)
>>>f(1, 2, 3, 4)(1, 2, 3, 4)

>>>def f(a, *pargs, **kargs): print(a, pargs, kargs)
>>>f(1, 2, 3, x=1, y=2)
1 (2, 3) {'y': 2, 'x': 1}

#解包参数

#元组
>>>def func(a, b, c, d): print(a, b, c, d)
...
>>>args = (1, 2)
>>>args += (3, 4)
>>>func(*args)
1 2 3 4

#字典
>>>args = {'a': 1, 'b': 2, 'c': 3}
>>>args['d'] = 4
>>>func(**args)

varargs调用语法 暂时不动有卵用

def tracer(func, *pargs, **kargs):         # Accept arbitrary arguments    
    print('calling:', func.__name__) 
    return func(*pargs, **kargs)           # Pass along arbitrary arguments

def func(a, b, c, d):    
    return a + b + c + d

print(tracer(func, 1, 2, c=3, d=4))

Keyword-Only参数

keyword-only参数——即必须只按照关键字传递并且不会由一个位置参数来填充的参数。

>>>def kwonly(a, *, b, c='spam'):
...    print(a, b, c)
...
>>>kwonly(1, b='eggs')
1 eggs spam

>>>kwonly(1, c='eggs')
TypeError: kwonly() needs keyword-only argument b

>>>kwonly(1, 2)
TypeError: kwonly() takes exactly 1 positional argument (2 given)

keyword-only参数必须在一个单个星号后面指定,而不是两个星号——命名的参数不能出现在**args任意关键字形式的后面,并且一个**不能独自出现在参数列表中。这两种做法都将产生语法错误:

#这里不用怀疑 语法分析 那块估计会有问题
>>>def kwonly(a, **pargs, b, c):
SyntaxError: invalid syntax
>>>def kwonly(a, **, b, c):
SyntaxError: invalid syntax
上一篇 下一篇

猜你喜欢

热点阅读