python——作用域

一、作用域

定义:作用域就是变量产生作用的范围。可以分为全局作用域和局部作用域(函数)。在代码运行中,不是所有变量都会一直保存,大多数变量是不断的建立和销毁,以此来避免内存被占用过多。

y = 2 # y就是全局作用域的全局变量

def fn():
    x = 1  # x是局部作用域中的变量

fn()

1.1 全局作用域

  1. 在代码中,全局作用域在程序执行时创建,在程序执行结束时销毁。
  2. 所有函数以外的都是全局作用域。
  3. 在全局作用域定义的变量都属于全局变量,全局变量可以在程序的任意位置被访问。
y = 2 # y就是全局作用域的全局变量

def fn():
    x = 1
    print('函数内部y=', y)  # 函数内部y= 2 # 因为y是全局变量,所以无论在程序哪里都可以调用

fn()
print('函数外部y=', y)  # 函数外部y= 2

1.2 局部作用域

  1. 函数作用域就是在函数调用时创建,在调用结束时销毁。
  2. 在函数作用域中定义的变量叫做局部变量,这个变量只能在函数内部被访问。
  3. 函数内部可以往外看,外部不可以往里面看。
def fn():
    a = 10
    print('a=', a)

# 调用fn()则创建局部作用域
fn()
# 调用结束销毁局部作用域

# 第二次调用再创建新的局部作用域
fn()
# 调用结束销毁
# 在函数作用域中定义的变量叫做局部变量,这个变量只能在函数内部被访问
def fn():
    a = 30
    print(a) # fn2中没有变量a,但外层函数中有变量a=30
fn()

def fn2():
    b = 20
    print(b)
    # print(a)  # 访问不了fn中的变量a,因为不属于同一个局部作用域
fn2()
# 可以往上一级找,也就是往外找
def fn():
    a = 30
    def fn2():
        print(a) # fn2中没有变量a,但外层函数中有变量a=30
    fn2()  # 30
fn()

# 外部不能往里找,所以程序直接报错
def fn2():
    def fn2():
        a = 30
    print(a)
fn2()

1.3 关键字 global

作用:在局部作用域中修改全局变量用到关键字global

# global使用在局部作用域中,也就是函数内
a = 1
def fn():
    global a
    a += 2
    print('内部a=', a)
fn()  # 内部a= 1

如果不使用global关键字,虽然在函数中也可以查看变量a的值,但是无法进行修改操作。

二、命名空间

定义:命名空间就是变量存放的位置。全局的命名空间保存全局变量,函数的命名空间保存局部变量或者说是函数中的变量。命名空间的数据类型是字典,简单来说就是用字典把所有的变量存储起来。

locals():获取当前作用域的命名空间
print(locals())

# 此时获取的是全局命名空间,字典中默认有许多内置的变量
"""
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x000001A527B13DC0>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'D:/pycharm_project/python147期学习/day_11/作用域与命名空间.py', '__cached__': None}
"""


# 我们增加一个变量a和定义一个函数fn,就可以看到全局命名空间的字典中有键a,和键fn
a = 1
def fn():
    pass
print(locals().keys())

dict_keys(['__name__', '__doc__', '__package__', '__loader__', '__spec__', '__annotations__', '__builtins__', '__file__', '__cached__', 'a', 'fn'])

# 再看看局部命名空间的情况
a = 1
def fn():
    b = 1
    print(locals())  # {'b': 1}
fn()

# 如果把b声明为全局变量,那么局部命名空间就成为空字典
a = 1
def fn():
    global b  # 把b声明为全局变量
    b = 1
    print(locals())  # {}
fn()

2.1 关键字nonlocal

定义:使用在局部,内嵌函数中,用来在函数或者其他作用域中使用外层(非全局)变量。

global是找全局变量,而nonlocal则是在嵌套函数中去找上一级函数,直到找到或者找不到报错。

# nonlocal 使用于嵌套函数中

def f():
    a = 1
    def f2():
        nonlocal a
        a += 1
        print(a)
    f2() 

f() # 2
# 不使用nonlocal时,变量只在自己的函数作用域中发挥作用,即使同名也不影响
def f1():
    a = 1
    def f2():
        a = 2
        print('f2的a', a)
    f2()
    print('f1的a', a)
f1()

f2的a 2
f1的a 1

# 使用nonlocal时,可以在别的函数作用域中修改另一个作用域的变量
def f1():
    a = 1
    def f2():
        nonlocal a  
        a = 2  # 此时外部函数f1中变量a的值变成2
        print('f2的a', a)
    f2()
    print('f1的a', a)
f1()

f2的a 2
f1的a 2

三、函数的高级用法

函数可以被引用(可以赋值)

def fn():
    print('我是fn')
f = fn # 通过赋值操作,此时f和fn都指向同一个地址
print(f,fn)
f() 

<function fn at 0x0000014AA246D310> <function fn at 0x0000014AA246D310>
我是fn

函数可以作为参数传入到另一个函数

# 实参也可以是函数对象
def fn():
    print('我是fn')

def fn2(x):
    x()  # 调用x相当于在调用fn

fn2(fn)

可以将函数作为返回值

def fn():
    print('我是fn')
    
def fn2(x):
    return x
x = fn2(fn)  # fn2(fn) 相当于fn
x()  # 相当于在调用fn

函数可以作为容器的元素

def fn():
    print('我是fn')

li = [1,2,3,fn]
f = li[3] # li[3]就是fn
f()
li[3]()

 

四、匿名函数 lambda

定义:匿名函数就是不需要显示的定义这一个函数,直接传入这个匿名函数。其实就是为了简化代码,对于一些简单的函数就不需要写太多,大大缩减了代码量。

语法:

lambda 参数列表:运算表达式

# 普通写法求平方
def fn(x):
    return x * x

print(fn(5))

# 匿名函数写法求平方
f = lambda x: x * x
print(f(5))

 总结:

  1. lambda并不会带来程序运行效率的提高,只会使代码更加的简洁
  2. 如果使用lambda,lambda内不要有循环,因为可读性不好。
  3. lambda只是为了减少单行函数的定义而存在,如果一个函数只有一个返回值,只有一句代码,就可以使用lambda

五、高阶函数

5.1 高阶内置函数简介

定义:高阶函数其实就是把函数作为参数传入,就是把一个函数作为另一个函数的参数传入。

# 定义一个函数,求任意两个数字的绝对值后进行求和
def ab_sum(a, b, f):
    return f(a) + f(b)


res = ab_sum(-1, -4, abs)  # abs是内置的求绝对值的函数
print(res)
# 求两个数相反数的和
def xfs(x):
    return -x

def ab_sum(a, b, f):
    return f(a) + f(b)
res = ab_sum(-1, -4, xfs)
print(res)


# 这个取反的函数很简单,就可以使用lambda来写
def ab_sum(a, b, f):
    return f(a) + f(b)
res = ab_sum(-1, -4, lambda x:-x)
print(res)

5.1.1 map()

作用:map就是改变序列中的所有元素,改变的规则由我们传入的函数来决定,map的返回结果其实是一个迭代器

语法:

map(function,seq)第一个参数是函数,第二个参数是序列类型

# 将列表中的各个元素加1
# 普通写法
li = [1, 2, 3, 4, 5]
def add1(x):
    return x+1
print(list(map(add1, li)))

# 匿名函数写法
li = [1, 2, 3, 4, 5]
print(list(map(lambda x: x + 1, li)))

5.1.2 filter()

作用:用于过滤序列,过滤掉不符合条件的元素,返回的也是一个迭代器对象,结果可以通过list()来转换。

语法:

filter(function,seq)第一个参数是函数,第二个参数是序列,

序列中的每一个元素作为参数传递给到函数进行判断,满足条件也就是结果为True的元素就会保存到新列表中
 

# 保留一个序列中所有的偶数
li1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
def o2x(x):
    return x % 2 == 0
print(list(filter(o2x,li1)))

# 匿名函数写法
li1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
print(list(filter(lambda x: x % 2 == 0, li1)))

5.1.3 sorted()

作用:排序

li = [2, 4, 1, 3, 5, 7, 6, 9]
print(sorted(li))  # 升序
print(sorted(li, reverse=True))  # 降序

li1 = ['火影:69', '路飞:90', '小明:79', '鸣人:100', '阿呆:45']
def f(x):
    arr = x.split(':')
    return int(arr[1])
print(sorted(li1,key=f))
# ['阿呆:45', '火影:69', '小明:79', '路飞:90', '鸣人:100']

# lambda写法可读性就差一些
li1 = ['火影:69', '路飞:90', '小明:79', '鸣人:100', '阿呆:45']
print(sorted(li1, key=lambda x: int(x.split(':')[1])))
# ['阿呆:45', '火影:69', '小明:79', '路飞:90', '鸣人:100']

5.2内置函数

python提供的,可以直接拿来用的函数

max,min,sorted即属于普通的内置函数也属于高阶内置函数,可以不传函数也能直接求值,map和filter就必须要传函数才可以进行求值

  • sum,求和

  • divmod,求商和余数

  • round,小数点后n位(四舍五入)

  • min,最小值

  • max,最大值

  • all,是否全部为True

  • any,是否存在True

  • bin,十进制转二进制

  • oct,十进制转八进制

  • hex,十进制转十六进制

  • ord,获取字符对应的unicode码点(十进制)

  • chr,根据码点(十进制)获取对应字符

  • enumerate, 可以将索引与元素组合为一个元组。

  • len,长度

  • print,打印

  • input,输入

  • type,查看类型

  • range,可创建一个整数列表,一般用在 for 循环中

  • id,查看内存地址

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值