python基础(7)-函数&命名空间&做用域&闭包

函数

动态参数

  • *args

     1 def sum(*args):
     2     '''
     3     任何参数都会被args以元组的方式接收
     4     '''
     5     print(type(args))  # result:<class 'tuple'>
     6     sum = 0
     7     for i in args:
     8         sum += i
     9     return sum
    10 
    11 
    12 print(sum(1, 2, 3))  # result:6
    13 print(sum(*[1, 2, 3]))  # result:6
    14 # 12,13行等价
    15 # * 表示将这个列表按照顺序打乱传入
  • **kwargs

     1 def info(**kwargs):
     2     '''
     3     参数都会被kwargs以字典的方式接收
     4     :param kwargs:
     5     :return:
     6     '''
     7     print(type(kwargs))  # result:<class 'dict'>
     8     for key in kwargs:
     9         print(key, kwargs[key], end=' ')
    10     print()
    11 
    12 
    13 info(name='张三', age=12, gender='')
    14 info(**{'name': '李四', 'age': 14, 'gender': ''})  # ** 将字典按顺序打乱传入
    15 # result:   name 张三 age 12 gender 男
    16 #           name 李四 age 14 gender 女

默认参数

  • 经过默认参数输出

     1 def name_sex_print(name, sex=''):
     2     print('姓名:{},性别:{}'.format(name, sex))
     3 
     4 name_sex_print('小强')
     5 name_sex_print('小兵')
     6 name_sex_print('小红', '')
     7 # result:
     8 # 姓名:小强,性别:男
     9 # 姓名:小兵,性别:男
    10 # 姓名:小红,性别:女
  • 默认参数陷阱

     1 def num_print(num_list=[]):
     2     num_list.append(1)
     3     print(num_list)
     4 
     5 num_print()
     6 num_print([])
     7 num_print()
     8 num_print()
     9 
    10 # result:
    11 # [1]
    12 # [1]
    13 # [1, 1]
    14 # [1, 1, 1]

    结论:若是默认参数的值是一个可变数据类型,那么每一次调用函数的时候,若是不传值就公用这个数据的资源python

函数的引用

  函数名实际上能够看作指向函数在内存中的引用(和C#中委托很相像)闭包

  • 赋值

    1 def func1():
    2     print('print in func1')
    3     
    4 func2 = func1;
    5 func2()
    6 #result:
    7 # print in func1
  • 函数的传递

     1 def func1():
     2     print('print in func1')
     3 
     4 def func2(func):
     5     print('print in func2')
     6     func()
     7 
     8 func2(func1)
     9 
    10 # result:
    11 # print in func2
    12 # print in func1

     

命名空间

命名空间的概述

  • 内置命名空间

    1.python解释器一启动就能够使用的变量及函数存放在内置命名空间内app

    2.内置的变量及函数在启动解释器的时候被加载进内存里ide

    3.不能使用局部和全局命名空间的函数及变量函数

  • 全局命名空间(本身写的非函数内部的代码)

    1.是在程序从上到下被执行的过程当中依次加载进内存的ui

    2.放置了咱们设置的全部变量名和函数名spa

    3.能够使用内置命名空间但不能使用局部命名空间中定义的变量及函数code

  • 局部命名空间

    1.定义在函数内部orm

    2.当调用函数的时候,才会产生这个名称空间,随着函数执行的结束,这个命名空间就又消失了blog

    3.能够使用全局及内置命名空间中的定义的变量及函数

三种命名空间的加载与取值顺序

  • 加载顺序

    内置命名空间(程序运行前加载)->全局命名空间(程序运行中:从上到下加载)->局部命名空间(程序运行中:函数调用时才加载)

  • 取值顺序

    局部命名空间->全局命名空间->内置命名空间

做用域

做用域概述

  做用域就是做用范围,按照生效范围能够分为全局做用域和局部做用域

  • 全局做用域

    包含内置名称空间、全局名称空间,在整个文件的任意位置都能被引用、全局有效

  • 局部做用域

    局部名称空间,只能在局部范围(函数内部)生效

查看局部变量和全局变量

  使用locals()和globals()函数可查看局部和全局变量

  • locals()

    1 def locals_func():
    2     b = 2
    3     c = 3
    4     print(locals())
    5 
    6 locals_func()
    7 # result:
    8 # {'b': 2, 'c': 3}
  • globals()

    1 a=1
    2 b=2
    3 print(globals())
    4 #result:
    5 # {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x0000000001D67208>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'E:/learning/python/test/0828/locals.py', '__cached__': None, 'a': 1, 'b': 2}

     

做用域链

  • 就近原则

    在函数内部使用一个变量时,会由近到远(由内而外)查找同名变量

     1 str = 'in globals'
     2 
     3 def fun1():
     4     str = 'in locals func1'
     5 
     6     def func2():
     7         str = 'in locals func2'
     8         print(str)
     9 
    10     func2()
    11 
    12 fun1()
    13 # result:
    14 # in locals func2
    View Code
     1 str = 'in globals'
     2 
     3 def fun1():
     4     str = 'in locals func1'
     5 
     6     def func2():
     7         # str = 'in locals func2'
     8         print(str)
     9     func2()
    10 
    11 fun1()
    12 # result:
    13 # in locals func1
    View Code
     1 str = 'in globals'
     2 
     3 def fun1():
     4     # str = 'in locals func1'
     5 
     6     def func2():
     7         # str = 'in locals func2'
     8         print(str)
     9 
    10     func2()
    11 fun1()
    12 # result:
    13 # in globals
    View Code 
  • nonlocal关键字

    使用要求:

    1.外部(非全局)必须有这个变量

    2.在内部函数声明nonlocal变量以前不能再出现同名变量

     1 def func1():
     2     a = 1
     3 
     4     def func2():
     5         nonlocal a
     6         a = 2
     7 
     8     func2()
     9     print(a)
    10 
    11 func1()
    12 # result:
    13 # 2

闭包

闭包函数的定义

    内部函数包含对外部做用域而非全局做用域名字的引用,该内部函数称为闭包函数

1 def outer():
2     a = 1
3 
4     def inner():
5         print(a)
6     return inner
7 
8 func = outer()
9 func()

闭包函数的判断

   可经过函数的__closure__属性判断该函数是不是一个闭包函数,若返回不是None,则就是闭包函数

def outer():
    a = 1
    def inner():
        b = a
        print(inner.__closure__)
    inner()
outer()
print(outer.__closure__)
#result:
# (<cell at 0x0000000000410108: int object at 0x000007FED797D420>, <cell at 0x0000000001DC82E8: function object at 0x00000000021CA730>)
# None

闭包的优缺点

  • 优势

    1.可以读取函数内部的变量

    2.让这些变量一直存在于内存中,不会在调用结束后,被垃圾回收机制回收

  • 缺点

    1.因为闭包会使函数中的变量保存在内存中,内存消耗很大,因此不能滥用闭包,解决办法是,退出函数以前,将不使用的局部变量删除

相关文章
相关标签/搜索