资讯专栏INFORMATION COLUMN

python开发第四篇--函数

lemanli / 1892人阅读

摘要:第一种情况打印结果为第二种打印结果为因为如果默认参数是一个可变的数据类型,那么他在内存中永远是一个。

名称空间与作用域

1.变量储存在一个内存空间中
2.当程序运行的时候代码从上到下依次执行,它会将变量与值的关系存储在一个空间中,这个空间叫名称空间,命名空间,全局名称空间
3.当程序遇到函数时,它会将函数名存在内存中,函数体漠不关心
4.当程序执行的时候,内存会临时开辟一个空间,存放函数体里的代码(变量,代码等)
5.函数外面访问不到临时空间的内容,随着函数执行完毕,临时名称空间会被释放掉,向这个临时开辟的空间也叫临时名称空间,也叫局部名称空间

python名称空间分为三种:
1.内置名称空间
2.全局名称空间
3.局部名称空间

按照作用域分为两种:

全局作用域

1.内置名称空间
2.全局名称空间

局部作用域

1.局部名称空间

加载顺序
内置名称空间---全局名称空间(当程序执行时)---局部名称空间(函数调用时)

取值顺序
局部名称空间(函数调用时)---全局名称空间(当程序执行时)---内置名称空间
注:取值顺序是单向不可逆的

  1.取值又叫引用,局部名称空间可以临时像全局名称空间引用,但是无法修改
  2.取值是从小到大取值LEGB
      - L=最里层的局部作用域
      - E=父亲级别的局部作用域
      - G=全局作用域中的全局名称空间
      - B=全局作用域中的内置名称空间

内置函数globals和locals的方法:

globles

   globales返回一个字典,字典里的内容是全局名称空间的内容

locals

   locals返回一个字典,当前位置的所有变量(看locals的位置是否在函数体里还是在全局里)

#1.
print(globals())
print(locals())
#打印结果:
{"__name__": "__main__", "__doc__": None, "__package__": None, "__loader__": <_frozen_importlib_external.SourceFileLoader object at 0x004DB4B0>, "__spec__": None, "__annotations__": {}, "__builtins__": , "__file__": "E:/python/day04/1.py", "__cached__": None}
{"__name__": "__main__", "__doc__": None, "__package__": None, "__loader__": <_frozen_importlib_external.SourceFileLoader object at 0x004DB4B0>, "__spec__": None, "__annotations__": {}, "__builtins__": , "__file__": "E:/python/day04/1.py", "__cached__": None}
#2.
def func():
    a = 12
    b = 20
    print(locals())
    print(globals())
func()
#打印结果:
{"b": 20, "a": 12}
{"__name__": "__main__", "__doc__": None, "__package__": None, "__loader__": <_frozen_importlib_external.SourceFileLoader object at 0x0044B4B0>, "__spec__": None, "__annotations__": {}, "__builtins__": , "__file__": "E:/python/day04/1.py", "__cached__": None, "func": }

关键字global和nonlocal的方法:

global
1.global可以引用全局变量,并且改变全局变量
2.在局部作用域声明一个全局变量

nonlocal
1.不能操作全局变量
2.在局部作用域中,对父级作用域(或者更外层作用域非全局作用域)的变量进行引用和修改,并且引用的哪层,从那层及以下此变量全部发生改变。

注:对于可变的数据类型list,dict,set,不用引用global,nonlocal
注:如果默认参数是一个可变的数据类型,那么他在内存中永远是一个。

#1.第一种情况:
def extendList(val,list=[]):
    list.append(val)
    return list
list1 = extendList(10)
print("list1=%s"%list1)  # [10,]
list2 = extendList(123,[])
print("list2=%s"%list2)  # [123,]
list3 = extendList("a")
print("list3=%s"%list3)  #[10,"a"]
打印结果为:
list1=[10]
list2=[123]
list3=[10, "a"]
#2.第二种:
def extendList(val,list=[]):
    list.append(val)
    return list
list1 = extendList(10)
list2 = extendList(123,[])
list3 = extendList("a")
print("list1=%s"%list1)
print("list2=%s"%list2)
print("list3=%s"%list3)
打印结果为:
list1=[10, "a"]
list2=[123]
list3=[10, "a"]
因为:如果默认参数是一个可变的数据类型,那么他在内存中永远是一个。

1.global实例:

def func():
    global a
    a = 3
func()
print(a)
#打印结果为:3
count = 1
def search():
    global count
    count = 2
search()
print(count)
#打印结果为2

2.nonloacl实例:

def add_b():
    b = 42
    def do_global():
        b = 10
        print(b)
        def dd_nonlocal():
            nonlocal b
            b = b + 20
            print(b)
        dd_nonlocal()  #30
        print(b) #30
    do_global()   #10
    print(b)
add_b()
#打印结果为:
10
30
30
42
函数

函数的嵌套与调用:

#函数的嵌套
def max2(x,y):
    m  = x if x>y else y
    return m
def max4(a,b,c,d):
    res1 = max2(a,b)
    res2 = max2(res1,c)
    res3 = max2(res2,d)
    return res3
#函数的调用
max4(1,2,3,4)

函数名的本质
1.打印函数名

def func():
    print("in func")
f = func
print(f)
#打印结果为:
为一块内存地址
2.函数名可以作为容器类数据的元素
def func1():
    print(111)
def func2():
    print(222)
def func3():
    print(333)
l1 = [func1, func2, func3]
for i in l1:
    i()
#打印结果为:
111
222
333
3.函数名可以作为函数的参数
def func1():
    print(111)
def func2(x):
    print(x)
    x()
    print(222)
func2(func1)
#打印结果为:

111
222
4.函数名可以作为函数的返回值
def func1():
    return 111
def func2(x):  # x = func1
    print(222)
    return x
ret = func2(func1)  # func1
print(ret())
print(ret)
#打印结果为:
222
111

总结:
函数名的应用,第一类对象

  - 函数名打印的出来的是个内存地址,加()号就可以运行
  - 函数名可以作为容器类型内的元素
  - 函数名可以作为传递的参数
  - 函数名可以作为函数的返回值,return把值给函数的执行者

闭包函数

  - 内层函数对外层函数非全局变量的引用,就叫做闭包
  - 判断是否是闭包:__closure__
  - 如果python解释器遇到了闭包,他有个机制,这个闭包不会随着函数的结束而释放
  - 装饰器@语法糖,装饰器放在需要装饰的函数的上边,利用的就是闭包函数

装饰器:

#测试func1函数的执行时间
def timmer(f):
    def inner(*args,**kwargs):
        start_time = time.time()
        ret = f(*args,**kwargs)
        end_time = time.time()
        print("此函数的执行效率%s" % (end_time - start_time))
        return ret
    return inner
@timmer
def func1():
    time.sleep(0.3)
    print("非常复杂......")
func1()
#格式为:
def wrapper(f):
    def inner(*args,**kwargs):
        """被装饰函数执行之前的操作"""
        ret = f(*args,**kwargs)
        """被装饰函数执行之后的操作"""
        return ret
    return inner
# 装饰器 本质就是闭包
# 装饰器根本作用:在不影响原函数执行的基础上,增加一些额外的功能登录认证,打印日志等等。

内裤可以用来遮羞,但是到了冬天它没法为我们防风御寒,聪明的人们发明了长裤,有了长裤后宝宝再也不冷了,装饰器就像我们这里说的长裤,在不影响内裤作用的前提下,给我们的身子提供了保暖的功效。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/41777.html

相关文章

  • 用十种编程语言开发计算器应用-四篇-Kotlin

    用十种编程语言开发计算器应用 C语言C#(windows桌面软件)Swift (ios应用)pythonDart(Flutter应用,跨平台,适用安卓、ios、mac、windows、web)Java(安卓App)Kotlin (安卓App)Js+Html+Vue(H5应用)微信小程序抖音小程序 安卓Kotlin语言版 开发工具 Android Studio 如何下载 工程截图 关键代码文...

    gclove 评论0 收藏0
  • 工具集核心教程 | 四篇: Velocity模板引擎入门到进阶

    摘要:是一个基于的模板引擎。模板中未被定义的变量将被认为是一个字符串。公众号回复全栈,领取前端,,产品经理,微信小程序,等资源合集大放送。公众号回复面试,领取面试实战学习资源。 Velocity是一个基于java的模板引擎(template engine)。它允许任何人仅仅简单的使用模板语言(template language)来引用由java代码定义的对象。 当Velocity应用于web...

    leon 评论0 收藏0
  • React Fiber源码分析 四篇(归纳总结)

    摘要:为什么网页性能会变高要回答这个问题,需要回头看是单线程的知识点。在分析的过程中,发现了的源码中使用了很多链式结构,回调链,任务链等,这个主要是为了增删时性能比较高 系列文章 React Fiber源码分析 第一篇 React Fiber源码分析 第二篇(同步模式) React Fiber源码分析 第三篇(异步状态) React Fiber源码分析 第四篇(归纳总结) 前言 Rea...

    jsdt 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<