017.Python之生成器、面向过程的编程思想、生成式以及三元表达式

目录
  • 一、生成器与yield
    • (一)什么是生成器
      • 1.生成器
      • 2.yield与return
    • (二)为什么要有生成器
    • (三)如何得到生成器(自定义的迭代器)
  • 二、面向过程的编程思想
    • (一)什么是编程思想
    • (二)什么是面向过程
    • (三)优点与缺点
      • 1.优点:
      • 2.缺点:
  • 三、三元表达式
    • (一)什么是三元表达式
    • (二)如何使用
  • 四、生成式
    • (一)列表生成式
    • (二)字典生成式
    • (三)集合生成式
    • (四)生成器表达式
      • 1.创建一个生成器对象有两种方式
  • 五、内置函数补充
    • (一)abs()
    • (二)all()
    • (三)any()
    • (四)callable()
    • (五)进制转换
    • (六)chr()与ord()
    • (七)divmod()
    • (八)enumerate()

一、生成器与yield

(一)什么是生成器

1.生成器

生成器就是一种自定义的迭代器,用来返回多次值。

2.yield与return

(1)return:

只能返回一次值,函数就立即结束了。

(2)yield

①可以挂起函数,保存函数的运行状态。

②可以用来返回多次值。

(二)为什么要有生成器

生成器(自定义迭代器)的优点:节省内存。

(三)如何得到生成器(自定义的迭代器)

在函数内一旦存在yield关键字,调用函数并不会执行函数体代码,会得到一个返回值,该返回值就是我们自定义的生成器。

# 先定义一个函数
def func():
    print('11111111111')
    print('11111111111')
    yield 1, 2
    print('22221222222')
    yield
    print('33333333333')
    yield 3
    print('44444444444')
    
g = func()
print(g)  # 
# 生成器内置有__iter__和__next__方法,所以生成器本身就是一个迭代器
# g.__iter__()
# g.__next__()

# 因而我们可以用next(生成器)触发生成器所对应函数的执行,然后遇到yield停下来,将yield后的值当做本次调用的结果返回
res1 = g.__next__() = next(g)  # 11111111111
							   # 11111111111
print(res1)  # (1, 2)

res2 = g.__next__() = next(g)  # 22221222222
print(res2)  # None

res3 = g.__next__() = next(g)  # 33333333333
print(res3)  # 3

next(g)  # 44444444444
		 # StopIteration

my_range小示例

# # 应用案列
def my_range(start,stop,step=1):
    while start < stop:
        yield start    #  函数中出现了yield,调用时已不能执行函数体代码,实际上已变成一个生成器generator
        start+=step

g=my_range(1,5) # 
print(next(g))  # 1  触发函数执行直到遇到yield则停止,将yield后的值返回,并在当前位置挂起函数
print(next(g))  # 2  再次调用next(g),函数从上次暂停的位置继续执行,直到重新遇到yield...
print(next(g))  # 3  重复上一步
print(next(g))  # 4  触发函数执行没有遇到yield则无值返回,即取值完毕抛出异常结束迭代StopIteration	

    
## 既然生成器对象属于迭代器,那么必然可以使用for循环迭代,如下:
for n in my_range(1,5):
    print(n) # 1 2 3 4

二、面向过程的编程思想

(一)什么是编程思想

编程思想就是编写程序的套路,与具体的技术点无关。

(二)什么是面向过程

面向过程核心是过程二字,过程就是解决问题的步骤,即先干啥、再干啥、后干啥,基于面向过程编程就好比在设计一条条的流水线。

(三)优点与缺点

1.优点:

将复杂的问题流程化、进而简单化。

2.缺点:

所有环节耦合到一起,环环相扣,如果要修改某个环境,有可能会牵一发而动全身,扩展性差。

三、三元表达式

(一)什么是三元表达式

三元表达式是python为我们提供的一种简化代码的解决方案,语法如下:

res = 条件成立时返回的值 if 条件 else 条件不成立时返回的值

(二)如何使用

针对下述场景

def func(x,y):
    if x > y:
        return x
    else:
        return y

res=func(1,2)
print(res)  # 2

用三元表达式可以一行解决

x=1
y=2

res=x if x > y else y
print(res)  # 2

四、生成式

(一)列表生成式

列表生成式是python为我们提供的一种简化代码的解决方案,用来快速生成列表。

# 列表生成式:
l = ['alex_nb', 'lxx_nb', 'wxx_nb', "xxq_nb", 'egon']
# 取出所有'nb'结尾的组成新的列表
new_l=[]
for name in l:
    if name.endswith('nb'):
        new_l.append(name)
print(new_l)  # ['alex_nb', 'lxx_nb', 'wxx_nb', 'xxq_nb']

new_l=[name for name in l if name.endswith('nb')]  # 快速生成新的列表,['alex_nb', 'lxx_nb', 'wxx_nb', 'xxq_nb']

# 把所有小写字母全变成大写
new_l=[name.upper() for name in l]
print(new_l)  # ['ALEX_NB', 'LXX_NB', 'WXX_NB', 'XXQ_NB', 'EGON']

# 把所有的名字去掉后缀_nb
new_l=[name.replace('_nb','') for name in l]
print(new_l)  # ['alex', 'lxx', 'wxx', 'xxq', 'egon']

(二)字典生成式

# 字典生成式
keys=['name','age','gender']
dic={key:None for key in keys}
print(dic)  # {'name': None, 'age': None, 'gender': None}

items=[('name','egon'),('age',18),('gender','male')]
res={k:v for k,v in items if k != 'gender'}
print(res)  # {'name': 'egon', 'age': 18}

(三)集合生成式

# 集合生成式
keys=['name','age','gender']
set1={key for key in keys}
print(set1,type(set1))  # {'gender', 'age', 'name'}  

(四)生成器表达式

1.创建一个生成器对象有两种方式

(1)一种是调用带yield关键字的函数,

(2)另一种就是生成器表达式,与列表生成式的语法格式相同,只需要将[]换成(),即:

(expression for item in iterable if condition)

对比列表生成式返回的是一个列表,生成器表达式返回的是一个生成器对象。对比列表生成式,生成器表达式的优点是节省内存(一次只产生一个值在内存中)。

g=(i for i in range(6) if i > 3)
# !!!!!!!!!!!强调!!!!!!!!!!!!!!!
# 此刻g内部一个值也没有

print(g,type(g))  #  at 0x000001F1CE13D9E0> 

print(next(g))  # 4
print(next(g))  # 5
print(next(g))  # StopIteration

如果我们要读取一个大文件的字节数,应该基于生成器表达式的方式完成

with open('a.txt', mode='rt', encoding='utf-8') as f:
    # 方式一:
    res=0
    for line in f:
        res+=len(line)
    print(res)

    # 方式二:
    res=sum([len(line) for line in f])
    print(res)

    # 方式三 :效率最高
    res = sum((len(line) for line in f))
    # 上述可以简写为如下形式
    res = sum(len(line) for line in f)
    print(res)

五、内置函数补充

(一)abs()

# 取绝对值
print(abs(-1))  # 1
print(abs(1))  # 1

(二)all()

# 2.1、传入的可迭代对象取出的值,全真则真,一假则假
# 2.2、如果传入的可迭代对象取不出任何值,默认返回True

print(all([1,1,1,True,"abc"]))  # True
print(all([1,"",1,True,"abc"]))  # False
print(all([]))  # True

(三)any()

# 3.1、传入的可迭代对象取出的值,一真则真,全假才假
# 3.2、如果传入的可迭代对象取不出任何值,默认返回False

print(any([0,None,False,"",1]))  # True
print(any([]))  # False

(四)callable()

# 判断一个变量是否可以加括号被调用为函数
def func():
    pass
print(callable(func))  # True
print(callable(len))  # True
print(callable(10))  # False

(五)进制转换

# 10进制转换为二  八  十六  进制
print(bin(11))  # 0b1011
print(oct(11))  # 0o13
print(hex(11))  # 0xb

(六)chr()与ord()

print(ord("a"))  # 97
print(chr(97))  # a

(七)divmod()

# 同时取到商与余数
print(divmod(10,3))  # (3, 1)

(八)enumerate()

# 得出可迭代对象的序号与值,迭代无序的字典类型也给出序号
l=[111,222,333]
for i,item in enumerate(l): #i,item=(0,111)
    print(i,item)
    
for i,item in enumerate({"k1":111,"k2":222}): #i,item=(0,111)
    print(i,item)

你可能感兴趣的:(017.Python之生成器、面向过程的编程思想、生成式以及三元表达式)