函数

动态参数

  • *args

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

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

默认参数

  • 通过默认参数输出

     def name_sex_print(name, sex='男'):
         print('姓名:{},性别:{}'.format(name, sex))
    
     name_sex_print('小强')
     name_sex_print('小兵')
     name_sex_print('小红', '女')
     # result:
     # 姓名:小强,性别:男
     # 姓名:小兵,性别:男
     # 姓名:小红,性别:女
  • 默认参数陷阱

     def num_print(num_list=[]):
         num_list.append(1)
         print(num_list)
    
     num_print()
     num_print([])
     num_print()
     num_print()
    
     # result:
     # [1]
     # [1]
     # [1, 1]
     # [1, 1, 1]

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

函数的引用

函数名实际上可以看做指向函数在内存中的引用(和C#中委托很相像)

  • 赋值

     def func1():
         print('print in func1')
    
     func2 = func1;
     func2()
     #result:
     # print in func1
  • 函数的传递

     def func1():
         print('print in func1')
    
     def func2(func):
         print('print in func2')
         func()
    
     func2(func1)
    
     # result:
     # print in func2
     # print in func1

命名空间

命名空间的概述

  • 内置命名空间

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

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

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

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

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

    2.放置了我们设置的所有变量名和函数名

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

  • 局部命名空间

    1.定义在函数内部

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

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

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

  • 加载顺序

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

  • 取值顺序

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

作用域

作用域概述

作用域就是作用范围,按照生效范围可以分为全局作用域和局部作用域

  • 全局作用域

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

  • 局部作用域

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

查看局部变量和全局变量

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

  • locals()

     def locals_func():
         b = 2
         c = 3
         print(locals())
    
     locals_func()
     # result:
     # {'b': 2, 'c': 3}
  • globals()

     a=1
     b=2
     print(globals())
     #result:
     # {'__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}

作用域链

  • 就近原则

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

     str = 'in globals'
    
     def fun1():
         str = 'in locals func1'
    
         def func2():
             str = 'in locals func2'
             print(str)
    
         func2()
    
     fun1()
     # result:
     # in locals func2
     str = 'in globals'
    
     def fun1():
         str = 'in locals func1'
    
         def func2():
             # str = 'in locals func2'
             print(str)
         func2()
    
     fun1()
     # result:
     # in locals func1
     str = 'in globals'
    
     def fun1():
         # str = 'in locals func1'
    
         def func2():
             # str = 'in locals func2'
             print(str)
    
         func2()
     fun1()
     # result:
     # in globals
  • nonlocal关键字

    使用要求:

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

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

     def func1():
         a = 1
    
         def func2():
             nonlocal a
             a = 2
    
         func2()
         print(a)
    
     func1()
     # result:
     

闭包

闭包函数的定义

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

 def outer():
     a = 1

     def inner():
         print(a)
     return inner

 func = outer()
 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.由于闭包会使函数中的变量保存在内存中,内存消耗很大,所以不能滥用闭包,解决办法是,退出函数之前,将不使用的局部变量删除

python基础(7)-函数&命名空间&作用域&闭包的更多相关文章

  1. python基础之函数详解

    Python基础之函数详解 目录 Python基础之函数详解 一.函数的定义 二.函数的调用 三.函数返回值 四.函数的参数 4.1 位置参数 4.2 关键字参数 实参:位置实参和关键字参数的混合使用 ...

  2. python基础——返回函数

    python基础——返回函数 函数作为返回值 高阶函数除了可以接受函数作为参数外,还可以把函数作为结果值返回.  我们来实现一个可变参数的求和.通常情况下,求和的函数是这样定义的: def calc_ ...

  3. python基础——匿名函数及递归函数

    python基础--匿名函数及递归函数 1 匿名函数语法 匿名函数lambda x: x * x实际上就是: def f(x): return x * x 关键字lambda表示匿名函数,冒号前面的x ...

  4. python基础——匿名函数

    python基础——匿名函数 当我们在传入函数时,有些时候,不需要显式地定义函数,直接传入匿名函数更方便.  在Python中,对匿名函数提供了有限支持.还是以map()函数为例,计算f(x)=x2时 ...

  5. python基础——sorted()函数

    python基础——sorted()函数 排序算法 排序也是在程序中经常用到的算法.无论使用冒泡排序还是快速排序,排序的核心是比较两个元素的大小.如果是数字,我们可以直接比较,但如果是字符串或者两个d ...

  6. python基础——filter函数

    python基础——filter函数 Python内建的filter()函数用于过滤序列. 和map()类似,filter()也接收一个函数和一个序列.和map()不同的是,filter()把传入的函 ...

  7. 八. Python基础(8)--函数

    八. Python基础(8)--函数 1 ● 函数返回布尔值 注意, 自定义的函数也可以是用来作逻辑判断的, 例如内置的startswith()等函数. def check_len(x):     ' ...

  8. Python进阶(三)----函数名,作用域,名称空间,f-string,可迭代对象,迭代器

    Python进阶(三)----函数名,作用域,名称空间,f-string,可迭代对象,迭代器 一丶关键字:global,nonlocal global 声明全局变量: ​ 1. 可以在局部作用域声明一 ...

  9. Python进阶(二)----函数参数,作用域

    Python进阶(二)----函数参数,作用域 一丶形参角度:*args,动态位置传参,**kwargs,动态关键字传参 *args: ​ 动态位置参数. 在函数定义时, * 将实参角度的位置参数聚合 ...

随机推荐

  1. Delphi如何处理在进行大量循环时,导致的应用程序没有响应的情况

    一般用在比较费时的循环中,往往导致应用程序没有响应,此时在比较费时的程序体中加入Application.ProcessMessages即可解决,该语句的作用是检查并先处理消息队列中的其他消息. 例如, ...

  2. AOSP中的HLS协议解析

    [时间:2018-04] [状态:Open] [关键词:流媒体,stream,HLS, AOSP, 源码分析,HttpLiveSource, LiveSession,PlaylistFetcher] ...

  3. windows下JDK环境配置与Android SDK环境配置

    一.JDK环境配置1.配置变量名:JAVA_HOME变量值:jdk安装的绝对路径. 变量名:Path(在系统变量中找到并选中Path点击下面的编辑按钮,不要删除原本变量值中的任何一个字母,在这个变量值 ...

  4. js对象与字符串的想到转换

    js JSON.stringify(jsObj);   对象转字符串JSON.parse(str);  字符串转对象

  5. Netty 学习笔记(1)通信原理

    前言 本文主要从 select 和 epoll 系统调用入手,来打开 Netty 的大门,从认识 Netty 的基础原理 —— I/O 多路复用模型开始.   Netty 的通信原理 Netty 底层 ...

  6. 卷积神经网络(Convolutional Neural Network, CNN)简析

    目录 1 神经网络 2 卷积神经网络 2.1 局部感知 2.2 参数共享 2.3 多卷积核 2.4 Down-pooling 2.5 多层卷积 3 ImageNet-2010网络结构 4 DeepID ...

  7. Go的json解析:Marshal与Unmarshal

    https://blog.csdn.net/zxy_666/article/details/80173288 https://www.jianshu.com/p/98965b3ff638

  8. Android用户点击返回按钮两次退出整个APP

    最近的APP项目有一个需求就是连续点击两次返回按钮,退出整个APP,而不是返回到上一个页面,这个连续是有时间限制的,在我的项目里,我设置成2秒钟,如果两秒之内点击了两次,就代表用户想要退出整个APP, ...

  9. [转]Visual Studio 2015源文件编码问题(936)

    在Visual Studio中,如果源文件中包含中文,那么当源文件编码为utf8时,会报“C4819 该文件包含不能在当前代码页(936)中表示的字符.请将该文件保存为 Unicode 格式以防止数据 ...

  10. Thinkpad L440 无线驱动突然无法使用,无法搜索到无线上网

    问题描述: 环境:Thinkpad L440,不知道是什么版本的,找朋友买的,买的时候连系统都没有,自己装的Win7系统,驱动均为官方网站下载安装.电脑在使用过程中一直带着电池,连接电源使用. 问题: ...