python函数作用域_Python 函数的作用域

作用域

标识符的可见范围就是作用域,也就是常说的变量的作用域

全局作用域

在整个代码运行环境内都可见

举例

x = 5def fn():

print(x)

fn()

运行结果

5

局部作用域

在函数、类内部可见。局部变量的范围不能超过其所在的局部作用域

def fn():

x= 5

returnx

print(fn())

运行结果

5

错误的使用作用域(函数内部变量不能被外部引用)

def fn():

x= 5

returnx

print(fn())

def fn1():

print(x) ## 这里上面fn函数中的x对fn1函数不可见

print(fn1())

print(x) ## x对全局不可见

嵌套函数中的作用域

def outer():

x= 10def inner():

print("inner {}".format(x))

print("outer {}".format(x))

inner()

outer()

运行结果

outer 10inner10

与上面函数中x变量的对比

def outer():

x= 10def inner():

x= 5print("inner {}".format(x))

print("outer {}".format(x))

inner()

outer()

运行结果

outer 10inner5

换一个执行顺序理解

def outer():

x= 10def inner():

x= 5print("inner {}".format(x))

inner()

print("outer {}".format(x))

outer()

运行结果

inner 5outer10

从结果可以看出:

(1)外层变量 x 的作用域在内层函数中可见

(2)内层函数中定义了变量 x,是重新定义的变量x,没有覆盖外层函数中的x。也就是说内层函数有本地定义的变量,优先用自己的

分析如下代码:

代码1

x = 1def fn():

y= x + 1print(y)

print(x)

fn()

运行结果

2

1

代码2

x = 1def fn():

y= x + 1print(y)

x+= 1## 这句开始报错

print(x) fn()

运行结果

Traceback (most recent call last):

y = x + 1UnboundLocalError: local variable 'x' referenced before assignment

报错是因为:x+=1等价x = x + 1,在函数本地定义了一个x变量,等式需要先计算右侧,这时本地没有变量x,x还没有赋值就被引用。

要解决上面的问题,就需要引入如下两个定义:本地变量和全局变量

全局变量 global

使用global关键字定义变量,将函数内的变量声明为全局作用域中的变量。global关键字后面的变量名必须在全局作用域中定义过

x = 1def fn():globalx

x+= 1print(x)

fn()

运行结果

2

全局作用域中没有定义x的情况

x = 10

def fn():globalx

x= 1x+= 1print(x)

fn()

print(x) ## 由于提升了作用域,外部定义的x值被覆盖了

运行结果

2

2

注意,这里的x的作用域还是全局的

不要使用global全局变量,因为这样破坏了函数的隔离性

global关键字定义变量的作用域

def outer():

x= 10def inner():globalx

x+= 1

returnxreturninner

foo=outer()

foo()

运行结果

Traceback (most recent call last):

x+= 1NameError: name'x' is not defined

global的作用域是当前定义global代码段和函数最外层(outer函数外)

默认值的作用域

def fn(abc=1):

print(abc)

fn()

print(abc) ## abc是形参,在函数的局部作用域中

运行结果

1Traceback (most recent call last):

File"C:/Users/ASUS-PC/PycharmProjects/复习/生成器.py", line 117, in print(abc)

NameError: name'abc' is not defined

函数的属性

Python使用元组报错函数默认值的属性

引用类型

def fn(abc=[]):

abc.append(1)

print(abc)

fn()

fn()

运行结果

[1]

[1, 1]

默认值可以在函数的属性中查看,函数的属性伴随着整个函数的生命周期

def fn(abc=[],a=1):

abc.append(1)

print(abc)

fn()

print(fn.__defaults__,id(fn))

fn()

print(fn.__defaults__,id(fn))

运行结果

[1]

([1], 1) 2304408771304[1, 1]

([1, 1], 1) 2304408771304

非引用类型

def fn(abc, a=1):

print(abc, a)

a= 'xyz'print(abc, a)

fn('python')

print(fn.__defaults__, id(fn))

fn('hello')

print(fn.__defaults__, id(fn))

运行结果

python 1python xyz

(1,) 1279837100776hello1hello xyz

(1,) 1279837100776

关键字参数的默认值属性

def fn(abc,*, a=1,b=2):

print(abc, a)

a= 'xyz'print(abc, a)

fn('python')

print(fn.__defaults__, id(fn))

fn('hello')

print(fn.__kwdefaults__, id(fn))

运行结果

python 1python xyz

None1995116403432hello1hello xyz

{'a': 1, 'b': 2} 1995116403432

使用浅拷贝的方式,避免修改实参的值

def fn(abc=[], *, a=1, b=2):

abc= abc[::-1]

abc.append(1)

print(abc)

fn()

print(fn.__defaults__, id(fn))

fn()

print(fn.__kwdefaults__, id(fn))

fn([1, 2])

print(fn.__defaults__, id(fn))

fn([1, 2, 5])

print(fn.__defaults__, id(fn))

运行结果

[1]

([],)1883111578344[1]

{'a': 1, 'b': 2} 1883111578344[2, 1, 1]

([],)1883111578344[5, 2, 1, 1]

([],)1883111578344

通过判断传入参数的值,决定修改传入对象的值还是创建新对象(非常常用)

def fn(abc=None, *, a=1, b=2):if abc isNone:

abc=[]

abc.append(1)

print(abc)

fn()

print(fn.__defaults__, id(fn))

fn([1, 2])

print(fn.__defaults__, id(fn))

fn([1, 2, 5])

print(fn.__defaults__, id(fn))

运行结果

[1]

(None,)2462419475176[1]

{'a': 1, 'b': 2} 2462419475176[1, 2, 1]

(None,)2462419475176[1, 2, 5, 1]

(None,)2462419475176

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值