函数

动态参数

  • *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. Oracle null判断并替换空值

      可用 NVL(), IFNULL() ,COALESCE(),DECODE() 函数 1.NVL() 从两个表达式返回一个非 null 值.语法NVL(eExpression1, eExpress ...

  2. 【Zookeeper】连接ZooKeeper的方式

    使用客户端命令连接Zookeeper 连接Server 使用命令./zkCli.sh -server 127.0.0.1:2181 使用JAVA连接使用ZK POM添加引用 <dependenc ...

  3. oracle学习创建和准备Oracle样例数据库

    此处有一个Oracle创建数据库和表和插入数据的脚本: http://www.forta.com/books/0672336073/

  4. 【C#】读取Excel中嵌套的Json对象,Json带斜杠的问题(其一)

    策划填Excel表时,约定对于复杂类型的数据采用Json的格式填写.如下图,D列的内容是Json数据. 单元格中的Json如下. { "name": "BeJson2&q ...

  5. Build GMP on 64bit Windows

    1.MSYS2 环境搭建 1.1.安装 msys2 的主页地址: http://www.msys2.org/ 下载32位或64位,我这里 下载了64位 msys2-x86_64-20161025.ex ...

  6. 集合的最大缺点是无法进行类型判定(这个缺点在JAVA1.5中已经解决),这样就可能出现因为类型不同而出现类型错误。

    集合的最大缺点是无法进行类型判定(这个缺点在JAVA1.5中已经解决),这样就可能出现因为类型不同而出现类型错误. 解决的方法是添加类型的判断.      LinkedList接口(在代码的使用过程中 ...

  7. java 中 热部署与卸载关系

    今天发现早年在大象笔记中写的一篇笔记,之前放在ijavaboy上的,现在它已经访问不了了.前几天又有同事在讨论这个问题.这里拿来分享一下. 在web应用开发或者游戏服务器开发的过程中,我们时时刻刻都在 ...

  8. springboot-custom starter

    Spring Boot由众多Starter组成,随着版本的推移Starter家族成员也与日俱增.在传统Maven项目中通常将一些层.组件拆分为模块来管理, 以便相互依赖复用,在Spring Boot项 ...

  9. A股主要指数的市盈率(PE)估值高度

    全指材料(SH000987) - 2019-03-18日,当前值:14.6662,平均值:29.73,中位数:25.66,当前 高于 6.91% 的交易日.全指材料(SH000987)的历史市盈率PE ...

  10. 本人SW知识体系导航 - Programming menu

    将感悟心得记于此,重启程序员模式. js, py, c++, java, php 融汇之全栈系列 [Full-stack] 快速上手开发 - React [Full-stack] 状态管理技巧 - R ...