Python Day 12 三元表达式、生成器表达式、列表与字典推导式、函数对象、名称空间、作用域

 阅读目录

     内容回顾

    函数默认值的细节

    三元表达式

    列表与字典推导式

    函数对象

    名称空间

    函数嵌套的定义

    作用域

  

  ##内容回顾

# 字符串的比较
     -- 按照从左往右比较每一个字符,通过字符对应的ascii进行比较

# 函数的参数
# 1)实参与形参:
    -- 形参:在函数定义时()中出现的参数 
    -- 实参:在函数调用时()中出现的参数

# 2)实参的分类
    -- 位置实参:给位置形参,必须按位置
    -- 关键字实参:给位置与关键字形参,不需要按顺序

# 3)形参的分类
    -- 无值位置
    -- 有值位置
     -- 可变长位置
    -- 有无值关键字
    -- 可变长关键字
def fn(a, b=10, *args, x, y=20, z, **kwargs): pass

# 4)打散机制
def func(*args, **kwargs):
    pass
func('a', 'b', 'c', a=1, b=2)
func(*'abc', **{'a': 1, 'b': 2})  # args=('a', 'b', 'c')  kwargs={'a': 1, 'b': 2}


# 函数的嵌套调用
     -- 在被调用的函数中调用其他函数:在被调用的函数中要去使用其他函数的功能

  ##函数默认值的细节

# 如果函数的默认参数的默认值为变量,在所属函数定义阶段一执行就被确定为当时变量存放的值
a = 100
def fn(num=a):
    print(num)  # 100
a = 200
fn()

  ##三元表达式:就是if....else...的语法糖

# 三目运算符:用于简化 if...else...的语法结构
       -- 1) 只能解决if...else...结构,其他if分支结构都不管
       -- 2)一个分支提供一个结果: 如果一个分支提供了多个结果, 将多个结果通过元组返回

a = int(input('a: '))
b = int(input('b: '))
res = a if a > b else b
print(res)

  ##列表与字典推导式

#目的: 能快速生成列表或字典的语法糖,且能在生成过程中添加简单的逻辑

# 能被列表推导式推导的数据源必须在循环取值时可以得到一个值
ls = [v for v in range(1, 6)]
print(ls)  # [1, 2, 3, 4, 5]

ls = ['奇数' if v % 2 != 0 else '偶数' for v in range(1, 6)]
print(ls)  # ['奇数', '偶数', '奇数', '偶数', '奇数']

 需求:解决10以内是3的倍数与不是3的倍数的排列方式
res = ['不是3的倍数' if v % 3 != 0 else '是3的倍数' for v in range(1, 10)]
print(res)

names=['alex','lqz','yyh','fm','egonSB']
l=[name + 'SB'for name in names]
print(l)
l1=[name for name in names if name.endswith('SB')]
print(l1)
# 能被字典推导式推导的数据源必须在循环取值时可以被解压赋值为两个值 ##快速理解(k,v 固定了) 
dic = {'a': 1, 'b': 2}
res
= {k: v for k, v in dic.items()}
print(res)
ls
= [['A', 1], ('B', 2)]
print(dict(ls)) ##快速理解(k,v 可以添加一些变化,例如k变为小写)
res = {k.lower(): v for k, v in ls}
print(res)
res
= {v: k.lower() for k, v in ls}
print(res)

eys=['name','age','sex']
vals=['egon',18,'male']
dic={}
for i,k in enumerate(keys):
dic[k]=vals[i]
print(dic)
dic={k:vals[i]for i,k in enumerate(keys)}
print(dic)

  ##生成器表达式

#简介:
  生成器表达式并不真正的创建数字列表,而是返回一个生成器对象,此对象在每次计算出一个条目后,把这个条目"产生"(yield)出来。生成器表达式使用了"惰性计算"或称作"延时求值"的机制。
  序列过长,并且每次只需要获取一个元素时,节省很大内存,列表推导式会全部声称在内存当中,所以应该考虑生成器表达式而不是列表解析。
#语法:
  (expression for iter_val in iterable)
  (expression for iter_val in iterable if cond_expr)

#示例:
N=(i**2 for i in range(1,11))
print(next(N))
print(next(N))
。。。
最后会抛异常
#示例二
with open('a.txt') as f:   
  g=(len(line) for line in f)
print(sum(g)) #为何报错?
#答案
g=(len(line) for line in f)  该⾏代码本质上是定义了⼀个⽣成器  并不是⼀个⽣成式 当在with作⽤域后使⽤g时 实际上是调⽤了上⾯定义的⽣成器,然⽽⽂件已经关闭 所以⽆法访问已经关闭的⽂件

  ##函数对象

# 在python中,所有变量存放的值只要是地址,我们就称之为对象
       -- 所有的变量都是用来存放地址的,所以都是对象
       -- 存放整型的地址就是整型对象 | 存放函数的地址就是函数对象 | 存放文件的地址就是文件对象

# 函数对象:存放函数地址的变量就是函数对象
def fn(): pass
my_fn = fn
# my_fn | fn都存着函数地址,所以都是函数对象,函数对象的使用就是 函数对象() 来调用函数


# 函数对象的应用场景
# 1.函数对象()就是调用函数
# 2.函数对象可以直接作为变量赋值给其他变量
# 3.函数对象可以作为函数的参数
# 4.函数对象可以作为函数的返回值
# 5.函数对象可以作为容器类型的成员


# 1.函数对象()就是调用函数
def fn1():
    pass
fn1()
# 2.函数对象可以直接作为变量赋值给其他变量
def fn2():
    pass
my_fn = fn2
print('>>>', my_fn, fn2)
my_fn()
# 3.函数对象可以作为函数的参数
def fn3(func):  # func = my_fn = fn2
    func()
fn3(my_fn)
# 4.函数对象可以作为函数的返回值
def fn4():
    return my_fn
my_fn2 = fn4()
# 5.函数对象可以作为容器类型的成员
ls = [my_fn, my_fn2]

   ##函数对象的案例

# part1
# 加法运算
def add(n1, n2):
    return n1 + n2

def low(n1, n2):
    return n1 - n2

# 四则运算
def computed(n1, n2, func):
    # if cmd == 'add':
    #     return add(n1, n2)
    # elif cmd == 'low':
    #     return n1 - n2
    return func(n1, n2)

r1 = computed(10, 20, add)
print(r1)
r2 = computed(10, 20, low)
print(r2)

# part2
def add(n1, n2):
    return n1 + n2

def low(n1, n2):
    return n1 - n2

def computed(n1, n2, func):
    return func(n1, n2)

cmd = input('cmd: ')  # 只能等于字符串add、low => 什么方式可以将字符串add、low对应上函数
# fn = None
# if cmd == 'add':
#     fn = add
# elif cmd == 'low':
#     fn = low
# computed(10, 20, fn)

fn_map = {
    'add': add,
    'low': low
}

if cmd in fn_map:  # 作为容器的成员可以简化判断逻辑
    fn = fn_map[cmd]
    res = computed(10, 20, fn)
    print(res)
else:
    print('该运算暂不支持')

# part3

def add(n1, n2):
    return n1 + n2

def low(n1, n2):
    return n1 - n2

def jump(n1, n2):
    return n1 * n2

def computed(n1, n2, func):
    return func(n1, n2)
fn_map = {
    'add': add,
    'low': low,
    'jump': jump
}

def get_fn(cmd):
    f = add  # 默认为add函数
    if cmd in fn_map:
        f = fn_map[cmd]  # 如果指令正确就返回对应的函数,如果不正确,就是采用默认的函数
    return f

while True:
    cmd = input('cmd: ')
    if cmd == 'q':
        break

    fn = get_fn(cmd)
    res = computed(10, 20, fn)
    print(res)


# while True:
#     cmd = input('cmd: ')
#     if cmd == 'q':
#         break
#     if cmd in fn_map:
#         fn = fn_map[cmd]  # 通过指令找函数
#         res = computed(10, 20, fn)
#         print(res)
#     else:
#         print('该运算暂不支持')


# part4

# 功能层
def add(n1, n2):
    return n1 + n2
def low(n1, n2):
    return n1 - n2

def jump(n1, n2):
    return n1 * n2

# 实现层
def computed(n1, n2, func):
    return func(n1, n2)

# 映射层
fn_map = {
    'add': add,
    'low': low,
    'jump': jump
}

# 完成映射对应
def get_fn(cmd):
    f = add  # 默认为add函数
    if cmd in fn_map:
        f = fn_map[cmd]  # 如果指令正确就返回对应的函数,如果不正确,就是采用默认的函数
    return f

# 程序入口
while True:
    cmd = input('cmd: ')
    if cmd == 'q':
        break

    fn = get_fn(cmd)
    res = computed(10, 20, fn)
    print(res)

  ##名称空间

# 名称空间:就是名字与地址的对应关系,可以被Python解释器遍历查找,采用堆栈存储方式(先进后出)

# 三种名称空间
# Built-in:内置名称空间;系统级,一个;随解释器执行而产生,解释器停止而销毁
# Global:全局名称空间;文件级,多个;随所属文件加载而产生,文件运行完毕而销毁
# Local:局部名称空间;函数级,多个;随所属函数执行而产生,函数执行完毕而销毁

# 注:文件中的if、while、for、with这些能产生缩减的关键字并不能产生名称空间
# 加载顺序:Built-in > Global > Local
# 查找顺序:Local -> Global -> Built-in 没有找到报错
#名称空间案例分析
# part1

# append操作的就是.前面的调用者,所以不需要返回值
# ls = []
# ls.append(10)
# print(ls)

# 名称空间
print(len)  # <built-in function len>
print(len('abc'))
len = 10

# 堆栈结构,优先访问到的是最后添加到结构中的变量
print(len)

del len

print(len)



# part2

print(len)

len = 10
print(len)

def fn():
    len = 20
    print(len)
fn()
def fn1():
    len = 30
    print(len)
fn1()


# part3
# 结论:在内置、全局、局部三个位置,只有出现了变量的定义,一定产生了自己名称空间中的名字,这些名字直接没有冲突
ls = []
def fn1():
    ls = []
    ls.append(10)
    print(ls)
def fn2():
    ls = []
    ls.append(20)
    print(ls)
fn1()
fn2()
print(ls)

  ##函数嵌套的定义

# 概念:在一个函数内部定义另一个函数
def outer():
    print('outer run')
    a = 10
    # 函数对象(变量)与普通对象(变量)一样,在函数内部定义,随函数调用而产生,
    # 调用结束而销毁,所以只能在函数内部调用
    def inner():
        print('inner run')
    inner()
outer()

  ##作用域

# 作用域:变量(名字|对象)起作用的范围
# 四种作用域
# Built-in:内置作用域:作用所有文件的所有地方
# Global:全局作用域:作用当前文件的所有地方
# Enclosing:嵌套作用域:作用当前函数已内部被嵌套函数
# Local:局部作用域:作用当前函数内部

# 注:
# 不同作用域之间名字不冲突,以达到名字的重用
# 每个作用域优先使用自己作用域中的名字,没有再找更大的名称空间的名字,直到内置,还没有就报错
# 查找顺序:Local > Enclosing > Global > Built-in

# 作用域:变量(名字|对象)起作用的范围
print(len)  # 1:内置
len = 1
def outer():
    len = 10
    def inner():
        len = 100
        print(len)  # 2:inner内部
    inner()
    print(len)  # 3:outer内部
outer()
print(len)  # 4: 全局
原文地址:https://www.cnblogs.com/liangzhenghong/p/10774508.html