三元表达式/递归

三元表达式、列表生成式、生成器表达式

 

 

三元表达式
def func(x, y): if x > y: return x else: return y res func(1,2) print(res) # 三元表达式: 条件成立时的返回值 if 条件 else 条件不成立时的返回值 def func(x,y): return x if x > y else y res = func(1,2) print(res)

  

列表生成式

 

l = ['rem_dlp', 'rushia_dlp', 'megumi_dlp']
harem = []
for girl in l:
    if girl.endswith('dlp')
    harem.append(girl)
    
    
# 列表生成式
'''
harem = [name for name in l if name..endswith('dlp')]
harem = [name for name in l]
'''
l = ['rem_dlp', 'rushia_dlp', 'megumi_dlp']
harem = [name.replace('_dlp', '').upper() for name in l if name.endswith('dlp')]
print(harem)

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

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

items=[('name', 'rem'), ('age', 16), ('gender', 'female')]
dic = {k: v for k, v in items if k != 'gender'}
print(dic)

  

生成器表达式

创建一个生成器对象有两种方式,一种是调用带yield关键字的函数

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

(expression for item in iterable if condition)

  

>>> [x*x for x in range(3)]
[0, 1, 4]
>>> g=(x*x for x in range(3))
>>> g
<generator object <genexpr> at 0x101be0ba0>

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

>>> next(g)
0
>>> next(g)
1
>>> next(g)
4
>>> next(g) #抛出异常StopIteration

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

with open('db.txt','rb') as f:
    nums=(len(line) for line in f)
    total_size=sum(nums) # 依次执行next(nums),然后累加到一起得到结果=

  

with open('db.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)

  

 

函数递归调用介绍

 

函数不仅可以嵌套定义,还可以嵌套调用,即在调用一个函数的过程中,函数内部又调用另一个函数,而函数的递归调用指的是在调用一个函数的过程中又直接或间接地调用该函数本身

例如

在调用f1的过程中,又调用f1,这就是直接调用函数f1本身

def f1():
    print('from f1')
    f1()
f1()

  

在调用f1的过程中,又调用f2,而在调用f2的过程中又调用f1,这就是间接调用函数f1本身

def f1():
    print('from f1')
    f2()

def f2():
    print('from f2')
    f1()

f1()

  

  • 可以使用sys.getrecursionlimit()去查看递归深度,默认值为1000
  • 虽然可以使用sys.setrecursionlimit()去设定该值,但仍受限于主机操作系统栈大小的限制
  • python不是一门函数式编程语言,无法对递归进行尾递归优化。

 

 

回溯与递推

下面我们用一个浅显的例子,为了让读者阐释递归的原理和使用:

例4.5

某公司四个员工坐在一起,问第四个人薪水,他说比第三个人多1000,问第三个人薪水,第他说比第二个人多1000,问第二个人薪水,他说比第一个人多1000,最后第一人说自己每月5000,请问第四个人的薪水是多少?

思路解析:

要知道第四个人的月薪,就必须知道第三个人的,第三个人的又取决于第二个人的,第二个人的又取决于第一个人的,而且每一个员工都比前一个多一千,数学表达式即:

 

思路解析:
要知道第四个人的月薪,就必须知道第三个人的,第三个人的又取决于第二个人的,第二个人的又取决于第一个人的,而且每一个员工都比前一个多一千,数学表达式即:
salary(4)=salary(3)+1000 
salary(3)=salary(2)+1000 
salary(2)=salary(1)+1000 
salary(1)=5000
总结为: 
salary(n)=salary(n-1)+1000 (n>1) 
salary(1)=5000 (n=1) 

很明显这是一个递归的过程,可以将该过程分为两个阶段:回溯和递推。
​ 在回溯阶段,要求第n个员工的薪水,需要回溯得到(n-1)个员工的薪水,以此类推,直到得到第一个员工的薪水,此时,salary(1)已知,因而不必再向前回溯了。然后进入递推阶段:从第一个员工的薪水可以推算出第二个员工的薪水(6000),从第二个员工的薪水可以推算出第三个员工的薪水(7000),以此类推,一直推算出第第四个员工的薪水(8000)为止,递归结束。需要注意的一点是,递归一定要有一个结束条件,这里n=1就是结束条件。

  

代码实现:

def salary(n):
    if n==1:
        return 5000
    return salary(n-1)+1000

s=salary(4)
print(s)

  

 

程序分析:

在未满足n\=\=1的条件时,一直进行递归调用,即一直回溯,见图4.3的左半部分。而在满足n\=\=1的条件时,终止递归调用,即结束回溯,从而进入递推阶段,依次推导直到得到最终的结果。

递归本质就是在做重复的事情,所以理论上递归可以解决的问题循环也都可以解决,只不过在某些情况下,使用递归会更容易实现,比如有一个嵌套多层的列表,要求打印出所有的元素,代码实现如下

items=[[1,2],3,[4,[5,[6,7]]]]
def foo(items):
    for i in items:
        if isinstance(i,list): #满足未遍历完items以及if判断成立的条件时,一直进行递归调用
            foo(i) 
        else:
            print(i,end=' ')

foo(items) #打印结果1 2 3 4 5 6 7

  使用递归,我们只需要分析出要重复执行的代码逻辑,然后提取进入下一次递归调用的条件或者说递归结束的条件即可,代码实现起来简洁清晰

 

 

posted @ 2020-03-25 21:31  清轩挽长风  阅读(319)  评论(0编辑  收藏  举报