函数

动态参数

  • *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. 云服务jdk 升级为 OpenJDK11

    由于oracle是个碧池,大家都懂,今年来,jdk版本更新的越来越频繁,所以目前商业版本需要收费了 每个企业都要考虑这样的问题,所以嘛,新项目试水肯定是要的,用openJDK11吧, https:// ...

  2. CentOS 7 安装GitLab

    CentOS 安装GitLab CentOS 安装GitLab GitLab是一个利用Ruby on Rails开发的开源应用程序,实现一个自托管的Git项目仓库,可通过Web界面进行访问公开的或者私 ...

  3. sql 视图 字段条件统计

    ) FModelCode,FProductTypeName,FBrandName,FOrganizationName,KOrganizationID,) FALLCount, end) SaleCou ...

  4. Linux服务器重启后eureka报错

    在Linux服务器重启后,首次启动应用时查看eureka注册中心,报错 EMERGENCY! EUREKA MAY BE INCORRECTLY CLAIMING INSTANCES ARE UP W ...

  5. SpringBoot系统列 2 - 配置文件,多环境配置(dev,qa,online)

    实现项目的多环境配置的方法有很多,比如通过在Pom.xml中配置profiles(最常见) 然后在Install项目打War包的时候,根据需求打不同环境的包,如图: 这种配置多环境的方法在SSM框架中 ...

  6. SpringBoot------ActiveMQ安装

    1.官网下载地址 http://activemq.apache.org/activemq-5156-release.html springboot文档 https://docs.spring.io/s ...

  7. JNDI数据源的配置

    一.数据源的由来 在Java开发中,使用JDBC操作数据库的四个步骤如下:   ①加载数据库驱动程序(Class.forName("数据库驱动类");)   ②连接数据库(Conn ...

  8. 【分布式系列】session跨域及单点登录解决方案

    Cookie机制 Cookie技术是客户端的解决方案,Cookie就是由服务器发给客户端的特殊信息,而这些信息以文本文件的方式存放在客户端,然后客户端每次向服务器发送请求的时候都会带上这些特殊的信息. ...

  9. C# StackExchange.Redis 用法总结

    安装 StackExchange.Redis 在 NuGet 中搜索 StackExchange.Redis 和 Newtonsoft.Json,直接点击按钮安装即可. StackExchange.R ...

  10. 【CF660E】Different Subsets For All Tuples 结论题

    [CF660E]Different Subsets For All Tuples 题意:对于所有长度为n,每个数为1,2...m的序列,求出每个序列的本质不同的子序列的数目之和.(多个原序列可以有相同 ...