day13 补充内容

01,三元表达式

语法格式: 条件成立时要返回的值 if 条件 else 条件不成立时要返回的值。

x = 1
y = 2
res = x if x > y else y
print(res)
def max1(x,y):
    if x > y:
        return x
    else:
        return y

def max2(x,y):
    n = x if x > y else y
    return n
max2(1,2)

02,生成式

1,列表生成式

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

[expression for item1 in iterable1 if condition1
for item2 in iterable2 if condition2
...
for itemN in iterableN if conditionN
]

#类似于
res=[]
for item1 in iterable1:
    if condition1:
        for item2 in iterable2:
            if condition2
                ...
                for itemN in iterableN:
                    if conditionN:
                        res.append(expression)

针对下述场景

egg_list=[]
for i in range(10):
    egg_list.append('鸡蛋%s' %i)

用列表生成式可以一行解决

egg_list=['鸡蛋%s' %i for i in range(10)]
案例1
l = []
for i in range(10):
    l.append(i)
print(l)

l = [i for i in range(10)]
print(l)
案例2
l = []
for i in range(10):
    if i > 5:
        l.append(i)
print(l)

l = [i for i in range(10) if i > 5]
print(l)

案例3:
names = ["lxx",'hxx',"wxx",'lili']
l = [name + "_sb" for name in names]
print(l)

案例4:
names = ["yyy","lxx_sb","hxx_sb","wxx_sb"]
res = [name for name in names if name.endswith("sb")]
print(res)

2,其他生成式

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

运行结果:
{'name': None, 'age': None, 'gender': None}
items = [('name','zhangsan'),('age','18'),('gender','male')]
res = {k:v for k,v in items}
print(res)
运行结果:
{'name': 'zhangsan', 'age': '18', 'gender': 'male'}
items = [('name','zhangsan'),('age','18'),('gender','male')]
res = {k:v for k,v in items if k != 'gender'}
运行结果:
{'name': 'zhangsan', 'age': '18'}
②集合生成式
keys = ['name','age','gender']
set1 = {key for key in keys}
print(set1)

运行结果:
{'gender', 'age', 'name'}
③生成器表达式

创建一个生成器对象有两种方式,一种是调用带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('c.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))
    # print(res)
    #方式三简化
    res = sum(len(line) for line in f)
    print(res)

02,递归函数

1,递归介绍

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

#方式一:while,for循环
while True:
    print(111)
    print(222)
    print(333)
#方式二:递归的本质就是循环:
def f1():
    print(111)
    print(222)
    print(333)
    f1()
f1()

大前提: 递归调用一定要在某一层结束
递归的两个阶段:
1、回溯:一层一层调下去
2、递推:满足某种结束条件,结束递归调用,然后一层一层返回

# age(5) = age(4) + 10
# age(4) = age(3) + 10
# age(3) = age(2) + 10
# age(2) = age(1) + 10
# age(1) = 18

def age(n):
    if n == 1:
        return 18
    return age(n-1) + 10

res = age(5)
print(res)

2,递归应用

nums = [1,[2,[3,[4,[5,[6,[7,]]]]]]]

def get(l):
    for num in l:
        if type(num) is list:
            get(num)
        else:
            print(num)

get(nums)

3,二分法

二分法是一个算法,算法是高效解决问题的办法。
需求:有一个按照从小到大顺序排列的数字列表,需要从该数字列表中找到我们想要的数字。

#方案一:整体遍历效率太低
nums = [-3,1,3,7,13,23,37,43,57,63,77,91,103]
find_num = 64
for num in nums:
    if num == find_num:
        print('find it')
        break
#方案二:二分法
def find(nums,find_num):
    print(nums)
    if len(nums) == 0:
        print("not exists")
        return
    mid_index = len(nums) // 2
    if find_num > nums[mid_index]:
        # in the right
        find(nums[mid_index+1:],find_num)
    elif find_num < nums[mid_index]:
        # in the left
        find(nums[:mid_index], find_num)
    else:
        print('you got it')

03,面向过程编程

面向过程的编程思想:
核心是“过程”二字,过程即流程,指的是做事的步骤:先什么,再什么,基于该思想编写程序就好比在设计一条流水线。
优点:复杂的问题流程化,进而简单化
缺点:扩展性非常差

应用场景
面向过程的程序设计一般用于那些功能一旦实现之后就很少需要改变的场景, 如果你只是写一些简单的脚本,去做一些一次性任务,用面向过程去实现是极好的,但如果你要处理的任务是复杂的,且需要不断迭代和维护, 那还是用面向对象最为方便。

04,函数式

函数式编程并非用函数编程这么简单,而是将计算机的运算视为数学意义上的运算,比起面向过程,函数式更加注重的是执行结果而非执行的过程,代表语言有:Haskell、Erlang。而python并不是一门函数式编程语言,但是仍为我们提供了很多函数式编程好的特性,如lambda,map,reduce,filter

1,匿名函数lambda

对比使用def关键字创建的是有名字的函数,使用lambda关键字创建则是没有名字的函数,即匿名函数,语法如下:

lambda 参数1,参数2,...: expression

举例

# 1、定义
lambda x,y,z:x+y+z

#等同于
def func(x,y,z):
    return x+y+z

# 2、调用
# 方式一:
res=(lambda x,y,z:x+y+z)(1,2,3)

# 方式二:
func=lambda x,y,z:x+y+z # “匿名”的本质就是要没有名字,所以此处为匿名函数指定名字是没有意义的
res=func(1,2,3)

匿名函数与有名函数有相同的作用域,但是匿名意味着引用计数为0,使用一次就释放,所以匿名函数用于临时使用一次的场景,匿名函数通常与其他函数配合使用,我们以下述字典为例来介绍它。

salaries={
    'siry':3000,
    'tom':7000,
    'lili':10000,
    'jack':2000
}

要想取得薪水的最大值和最小值,我们可以使用内置函数max和min(为了方便开发,python解释器已经为我们定义好了一系列常用的功能,称之为内置的函数,我们只需要拿来使用即可

>>> max(salaries)
'tom'
>>> min(salaries)
'jack'

内置max和min都支持迭代器协议,工作原理都是迭代字典,取得是字典的键,因而比较的是键的最大和最小值,而我们想要的是比较值的最大值与最小值,于是做出如下改动

# 函数max会迭代字典salaries,每取出一个“人名”就会当做参数传给指定的匿名函数,然后将匿名函数的返回值当做比较依据,最终返回薪资最高的那个人的名字
>>> max(salaries,key=lambda k:salaries[k]) 
'lili'
# 原理同上
>>> min(salaries,key=lambda k:salaries[k])
'jack'

同理,我们直接对字典进行排序,默认也是按照字典的键去排序的

>>> sorted(salaries)
['jack', 'lili', 'siry', 'tom']
posted @ 2020-12-31 20:11  小熊渣渣  阅读(57)  评论(0)    收藏  举报