python day10

 

1.默认参数的陷阱

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

 

 

2.函数的命名空间

2.1 函数的进阶

命名空间和作用域:

#内置命名空间

  #就是python解释器,例如print,input,len,list等,一启动就可以使用的名字存储在内置命名空间中。

  #内置的名字在启动解释器的时候被加载进内存里。

#全局命名空间

  #是在程序从上到下被执行的过程中依次加载进内存的放置了我们设置的所有变量名和函数名

#局部命名空间

  #就是函数内部定义的名字

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

#在正常情况下,直接使用内置的名字
#当我们在全局定义了和内置名字空间中同名的名字时,会使用全局的名字
#当我自己有的时候 我就不找我的上级要了
#如果自己没有 就找上一级要 上一级没有再找上一级 如果内置的名字空间都没有 就报错
# 多个函数应该拥有多个独立的局部名字空间,不互相共享

 

# 作用域两种
# 全局作用域 —— 作用在全局 —— 内置和全局名字空间中的名字都属于全局作用域 ——globals()
# 局部作用域 —— 作用在局部 —— 函数(局部名字空间中的名字属于局部作用域) ——locals()

# 对于不可变数据类型 在局部可以查看全局作用域中的变量,但是不能直接修改;如果想要修改,需要在程序的一开始添加global声明,如果在一个局部(函数)内声明了一个global变量,那么这个变量在局部的所有操作将对全局的变量有效

a = 1
def func():
    global a
    a = 2
func()
print(a)

#globals 永远打印全局的名字

#locals 输出什么 根据locals所在的位置

a = 1
b = 2
def func():
    x = 'aaa'
    y = 'bbb'
    print(locals())
    print(globals())
func()
print(globals())
print(locals()) #本地的

#尽量避免使用global 

 通过下图完成a的修改,会更加的安全。

3、函数的嵌套和作用域链

def max(a,b):
    return a if a>b else b

def the_max(x,y,z):  #函数的嵌套调用
    c = max(x,y)
    return max(c,z)
print(the_max(1,2,3))

def outer():
    a = 1
    def inner():
        print("inner")
        def inner2():
            print(a)
            print("inner2")
        inner2()
    inner()
outer()

 结果:

inner
1
inner2
声明了一个上面最近一层局部变量,如果上一层没有就再向上,但是只能是局部变量
a = 1
def outer():
    a = 1
    def inner():
        a = 2
        def inner2():
            nonlocal a  #声明了一个上面第一层局部变量
            a += 1   #不可变数据类型的修改
        inner2()
        print('##a## : ', a)
    inner()
    print('**a** : ',a)

outer()
print('全局 :',a)

  结果:

##a## :  3
**a** :  1
全局 : 1  

#nonlocal 只能用于局部变量 找上层中离当前函数最近一层的局部变量
#声明了nonlocal的内部函数的变量修改会影响到 离当前函数最近一层的局部变量
# 对全局无效
# 对局部 也只是对 最近的 一层 有影响

  

 

def func():
    print(123)

# func()  #函数名就是内存地址
func2 = func  #函数名可以赋值
func2()

l = [func,func2] #函数名可以作为容器类型的元素
print(l)
for i in l:
    i()

  

 

def func():
    print(123)

def wahaha(f):
    f()
    return f           #函数名可以作为函数的返回值

qqxing = wahaha(func)   # 函数名可以作为函数的参数
qqxing()

函数名的本质                                                                                                                                                                

函数名本质上就是函数的内存地址

1.可以被引用

def func():
    print('in func')

f = func
print(f)
函数被引用

2.可以被当作容器类型的元素

def func():
    print(123)

# func()  #函数名就是内存地址
func2 = func  #函数名可以赋值
func2()

l = [func,func2] #函数名可以作为容器类型的元素
print(l)
for i in l:
    i()
函数被当作容易类型的元素
def f1():
    print('f1')


def f2():
    print('f2')


def f3():
    print('f3')

l = [f1,f2,f3]
d = {'f1':f1,'f2':f2,'f3':f3}
#调用
l[0]()
d['f2']()

函数被当作容易类型的元素
函数被当作容易类型的元素2

3.可以当作函数的参数和返回值

第一类对象(first-class object)指
1.可在运行期创建
2.可用作函数参数或返回值
3.可存入变量的实体。
第一类对象

 4、闭包                                                                                                                                                                        

例子:

#闭包:嵌套函数,内部函数调用外部函数的变量
def outer():
    a = 1
    def inner():
        print(a)
    inner()
outer()

判断闭包函数的方法__closure__

#输出的__closure__有cell元素 :是闭包函数

#输出的__closure__为None :不是闭包函数

def outer():
    a = 1
    def inner():
        print(a)
    print(inner.__closure__)
outer()
print(outer.__closure__)

结果:

(<cell at 0x00000000056D3CD8: int object at 0x000000001D3B60A0>,)
None

闭包常用形式:在函数outer之外调用outer内部的函数。

def outer():
    a = 1
    def inner():
        print(a)
    return inner
inn = outer()
inn()

 

import urllib  #模块
from urllib.request import urlopen
ret = urlopen('http://www.xiaohua100.cn/index.html').read()
print(ret)
def get_url():
    url = 'http://www.xiaohua100.cn/index.html'
    ret = urlopen(url).read()
    print(ret)
get_url() 

def get_url():
    url = 'http://www.xiaohua100.cn/index.html'
    def get():
        ret = urlopen(url).read()
        print(ret)
    return get

get_func = get_url()
get_func()
example

 

posted @ 2018-12-03 18:15  李然然  阅读(155)  评论(0编辑  收藏  举报