Python学习日记-14-函数

def f():
    print('ok')

f()   #  ok
def add(x,y):
    print(x + y)

add(3,5)      # 8
def print_info(name, age, sex='male'):        # 默认参数一定要跟在其他参数后面
    print('Name: %s'% name)
    print('Age: %d' % age)
    print('Sex: %s' % sex)


print_info('kkk',18)                           # 必需参数
print_info(name='ooo', age=18)                 # 关键字参数
print_info(name='ppp', age=18, sex='famale')   # 默认参数
def add(*args):        # 不定长参数
    print(args)
    Sum = 0
    for i in args:     # 将参数做成元组
        Sum += i
    print(Sum)

add(2, 6)
def print_info(p='ll', *args, **kwargs):       # 将参数做成一个字典
    print(p)
    print(args)                        # ('ooo', 'ee', 25)
    print(kwargs)                      # {'name': 'zhr', 'age': 18, 'sex': 'male'}

    for i in kwargs:
        print(i, kwargs[i])

print_info('ooo', 'ee', 25, name='zhr', age=18, sex='male')
# 顺序:关键字参数  ->  默认参数  ->   *args  ->   **kwargs
def add(*args):        # 不定长参数
    Sum = 0
    for i in args:     # 将参数做成元组
        Sum += i
    return Sum         # 结束函数,返回值
                       # 函数里如果没有return,会默认返回None

print(add(3, 6))  # 9
def foo():
    return 1, 'oo', 89   # ruturn 多个对象会把多个对象封装成一个元组返回

print(foo())     # (1, 'oo', 89)

作用域
L(local)局部作用域

局部变量:包含在def关键字定义的语句块中,即在函数中定义的变量。每当函数被调用时都会创建一个新的局部作用域。Python中也有递归,即自己调用自己,每次调用都会创建一个新的局部命名空间。在函数内部的变量声明,除非特别的声明为全局变量,否则均默认为局部变量。有些情况需要在函数内部定义全局变量,这时可以使用global关键字来声明变量的作用域为全局。局部变量域就像一个 栈,仅仅是暂时的存在,依赖创建该局部作用域的函数是否处于活动的状态。所以,一般建议尽量少定义全局变量,因为全局变量在模块文件运行的过程中会一直存在,占用内存空间。注意:如果需要在函数内部对全局变量赋值,需要在函数内部通过global语句声明该变量为全局变量。

E(enclosing)嵌套作用域

E也包含在def关键字中,E和L是相对的,E相对于更上层的函数而言也是L。与L的区别在于,对一个函数而言,L是定义在此函数内部的局部作用域,而E是定义在此函数的上一层父级函数的局部作用域。主要是为了实现Python的闭包,而增加的实现。

G(global)全局作用域

即在模块层次中定义的变量,每一个模块都是一个全局作用域。也就是说,在模块文件顶层声明的变量具有全局作用域,从外部开来,模块的全局变量就是一个模块对象的属性。注意:全局作用域的作用范围仅限于单个模块文件内。

B(built-in)内置作用域

系统内固定模块里定义的变量,如预定义在builtin 模块内的变量。

def func():                # 在作用域中定义的变量,一般只在作用域中有效。
    variable = 100
    print (variable)

print (variable)        #NameError: name 'variable' is not defined
if True:                     # 需要注意的是:在if-elif-else、for-else、while、try-except\try-finally
                             # 等关键字的语句块中并不会产成作用域
    variable = 100
    print (variable)
print ("******")
print (variable)
def func():
    variable = 300
    print (variable)

variable = 100
func()            #300
print (variable)  #100
variable = 300
def test_scopt():
    print (variable)    #variable是test_scopt()的局部变量,但是在打印时并没有绑定内存对象。
    variable = 200      #因为这里,所以variable就变为了局部变量
test_scopt()
print (variable)

上面的例子会报出错误,因为在执行程序时的预编译能够在test_scopt()中找到局部变量variable(对variable进行了赋值)。在局部作用域找到了变量名,所以不会升级到嵌套作用域去寻找。但是在使用print语句将变量variable打印时,局部变量variable并有没绑定到一个内存对象(没有定义和初始化,即没有赋值)。本质上还是Python调用变量时遵循的LEGB法则和Python解析器的编译原理,决定了这个错误的发生。所以,在调用一个变量之前,需要为该变量赋值(绑定一个内存对象)。注意:为什么在这个例子中触发的错误是UnboundLocalError而不是NameError:name ‘variable’ is not defined。因为变量variable不在全局作用域。Python中的模块代码在执行之前,并不会经过预编译,但是模块内的函数体代码在运行前会经过预编译,因此不管变量名的绑定发生在作用域的那个位置,都能被编译器知道。Python虽然是一个静态作用域语言,但变量名查找是动态发生的,直到在程序运行时,才会发现作用域方面的问题。

你可能感兴趣的:(Python学习日记-14-函数)