python变量后加点和函数_python 函数 变量和闭包

首先我们认定,python中定义域查找遵循local->Enclosing->Global->Built-in顺序:

a=1

def func1():

... print(a)

... a=111

... print(a)

...

func1()

Traceback (most recent call last):

File "", line 1, in

File "", line 2, in func1

UnboundLocalError: local variable 'a' referenced before assignment

而:

a=1

def fun():

... print(a)

... b=111

... print(b)

...

fun()

1

111

print(b)

Traceback (most recent call last):

File "", line 1, in

NameError: name 'b' is not defined

我们可以得出结论(打脸):内置函数先在内置函数定义域内(前后)寻找变量;找不到之后再从全局变量中引进,且局部变量无法全局。

如果global:

a=1

def func1():

... global a

... print(a)

... a=111

... print(a)

...

func1()

1

111

a

111

但是不多久后我发现一个问题,代码如下:

a=10

def test():

... a = a + 1

... print(a)

...

test()

Traceback (most recent call last):

File "", line 1, in

File "", line 2, in test

UnboundLocalError: local variable 'a' referenced before assignment

test(a)

Traceback (most recent call last):

File "", line 1, in

TypeError: test() takes 0 positional arguments but 1 was given

所以这个问题其实可以被拆分为两个问题,一个是arguments的问题,还有一个是variable的问题。

当定义了一个argument的时候只要在括号里把global中的variable代入就是可以运行的,前提就是可一定要定义啊!!!

a=1

def func1(a):

... print(a)

... a=111

... print(a)

...

func1(a)

1

111

也就是说问题根本不在global,而是我有没有把a带进去...(哭泣)

结论就是一切都是我自作多情想多了,自己的bug

a=10

def test(a):

... print(a)

... a=a+1

... print(a)

...

test(a)

10

11

所以回到第一个例子,所谓的“local variable referred before assignment”只是因为我没有把变量在定义的时候放进去。

这是第一件事

第二件:只有模块,类以及函数才会引入新的定义域,其他代码块如(if/else,while)是不会的:

a=0

while a < 4:

... print(a)

... a += 1

...

0

1

2

3

a

4

三: 嵌套和闭包

def out():

... a=7

... def inner():

... nonlocal a

... print(a)

... a=9

... print(a)

... inner()

... print(a)

...

out()

7

9

9

嵌套和nonlocal都超好理解

让我斯巴达的是如下:

def fun2(a):

... print(a)

... def fun3(b):

... print(a,b)

... return fun3 #返回fun3函数结果

...

fun2(1)

1

.fun3 at 0x000001E2857C24C8>

f=fun2(1)

1

f

.fun3 at 0x000001E2857A4828>

f(4)

1 4

嗯这就是传说中的闭包,闭包使得函数内部的变量可以一直被保存并且被外部使用(像个自由的包裹一直裹着里面的变量)

为了更直观一点:

def out():

... def inner():

... a=5

... return a

... inner()

... return inner

...

f=out()

f

.inner at 0x000001E2857A4678>

f()

5

可见调用的这个定义函数,返回的仍旧是一个函数,而不是一个值。out()不是一个函数运行结果而是一个由返回的inner函数和变量a构成的函数(因为闭包的本质就是一种函数,由局部变量和内部函数构成)。

具体一点说来,在第一个例子中,运行fun2(1)将同时得到print出来的一个a,和一个以fun3为函数,被保留的a和未被赋值的b为变量的函数。【当定义符合闭包条件时,自由变量(此处的f)变成一个闭包类,有函数的效果】。

至于为什么它的地址在变化,我觉得是因为它每次调用都返回了一个新函数(分开储存)。

233333我又看到了一个神奇东西

def count():

... fs=[]

... for i in range(1,4):

... def f():

... return i*i

... fs.append(f)

... return fs

...

f1,f2,f3=count()

f1

.f at 0x000001E2857A4438>

f1()

9

f2()

9

f3()

9

此处函数为闭包的原因在于append的那个f,如果我做一个改动

def count():

... fs=[]

... for i in range(1,4):

... def f():

... return i*i

... fs.append(f())

... return fs

...

count()

[1, 4, 9]

它就不是闭包了,count可以正常输出结果。

而在这里,返回的函数是i*i,但是由于返回时i=3,f1,f2,f3都变成了9。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值