day20-python-二分、面向过程思想、函数式、模块

昨日内容回顾

1、叠加多装饰器
    @deco1     => wrapper1
    @deco2     => wrapper2
    @deco3(1)  => wrapper3
    def index():
        pass

2、yield(了解)
    x=yield 返回值

    next(g)
    g.send(1)

3、三元表达式
    res=值1 if 条件 else 值2

4、生成式
    l=[表达式 for x in 可迭代对象 if 条件]


    g=(表达式 for x in 可迭代对象 if 条件)
    next(g)
    sum(表达式 for x in 可迭代对象 if 条件)
    list(表达式 for x in 可迭代对象 if 条件)


    dic={键:值 for k in 可迭代对象 if 条件}
    set1={元素 for k in 可迭代对象 if 条件}

5、函数的递归调用
    def f1():
        print(1111)
        print(2222)
        f2()


    def f2():
        print(2222)
        f1()

    f1()


 def f1():
    print(1111)
    print(2222)
    print(3333)
    f1()

今日内容概要

1、二分法
2、面向过程编程思想
3、函数式
    lambda
    map
    filter
    reduce

    sorted
    max
    min

4、模块

今日内容详细

二分法

算法:是高效解决问题的办法
算法之二分法

需求:有一个按照从小到大顺序排列的数字列表
需要从该数字列表中找到我们想要的那个一个数字
如何做更高效???


nums = [-3, 4, 7, 10, 13, 21, 43, 77, 89]
find_num = 10

nums = [-3, 4, 13, 10, -2, 7, 89]
nums.sort() # 二分的前提,序列有序,或者有一个明确的分解点
print(nums)

方案一:整体遍历效率太低

for num in nums:
    if num == find_num:
        print('find it')
        break

方案二:二分法

伪代码模板

def binary_search(find_num, 列表):
    mid_val = 找列表中间的值
    if find_num > mid_val:
        # 接下来的查找应该是在列表的右半部分
        列表 = 列表切片右半部分
        binary_search(find_num, 列表)
    elif find_num < mid_val:
        # 接下来的查找应该是在列表的左半部分
        列表 = 列表切片左半部分
        binary_search(find_num, 列表)
    else:
        print('find it')

示范

nums = [-3, 4, 7, 10, 13, 21, 43, 77, 89]
find_num = 8


def binary_search(find_num, l):
    print(l)
    if len(l) == 0:
        print('找的值不存在')
        return
    mid_index = len(l) // 2

    if find_num > l[mid_index]:
        # 接下来的查找应该是在列表的右半部分
        l = l[mid_index+1:]
        binary_search(find_num, l)
    elif find_num < l[mid_index]:
        # 接下来的查找应该是在列表的左半部分
        l = l[:mid_index]
        binary_search(find_num, l)
    else:
        print('find it')

binary_search(find_num, nums)

面向过程编程思想

编程思想/范式

面向过程的编程思想:
     核心是"过程"二字,过程即流程,指的是做事的步骤:先什么、再什么、后干什么
     基于该思想编写程序就好比在设计一条流水线

优点:复杂的问题流程化、进而简单化
缺点:扩展性非常差

面向过程的编程思想应用场景解析:
1、不是所有的软件都需要频繁更迭:比如编写脚本
2、即便是一个软件需要频繁更迭,也不并不代表这个软件所有的组成部分都需要一起更迭

函数式

1、def用于定义有名函数

func = 函数的内存地址
def func(x, y):
    return x+y

print(func)

2、lamdab用于定义匿名函数

print(lambda x, y: x+y)

3、调用匿名函数

res = (lambda x, y: x+y)(1, 2)
print(res)

4、匿名函数作用

用于临时调用一次的场景:更多的是将匿名与其他函数配合使用

5、匿名函数的示范

from functools import reduce

salaries = {
    'siry': 3000,
    'tom': 7000,
    'lili': 10000,
    'jack': 2000
}
max的应用
res = max(salaries)
print(res)

def func(k):
    return salaries[k]

res = max(salaries, key=func)  # 返回值=func('siry')
print(res)

res = max(salaries, key=lambda k: salaries[k])
print(res)
min的应用
res = min(salaries, key=lambda k: salaries[k])
print(res)
sorted排序

res = sorted(salaries, key=lambda k: salaries[k], reverse=True)
print(res)

map的应用(了解)

下面两个返回的都是生成器

l = ['alex', 'lxx', 'wxx', '薛贤妻']
new_l = (name+'_dsb' for name in l)
print(new_l)

res = map(lambda name: name+'_dsb', l)
print(res)  # 生成器
filter的应用(了解)
l = ['alex_sb', 'lxx_sb', 'wxx', '薛贤妻']
res = (name for name in l if name.endswith('sb'))
print(res)

res = filter(lambda name: name.endswith('sb'), l)
print(res)
reduce的应用(了解)
res = reduce(lambda x, y: x+y, [1, 2, 3], 10)  # 16
print(res)

res = reduce(lambda x, y: x+y, ['a', 'b', 'c'])  # 'a','b'
print(res)

模块

什么是模块?

模块就是一系列功能的集合体, 分为三大类
I:内置的模块
II:第三方的模块
III:自定义的模块
一个python文件本身就一个模块,文件名m.py,模块名叫m

模块的形式

模块有四种形式
    1 使用python编写的.py文件

    2 已被编译为共享库或DLL的C或C++扩展

    3 把一系列模块组织到一起的文件夹(注:文件夹下有一个__init__.py文件,该文件夹称之为包)

    4 使用C编写并链接到python解释器的内置模块

为何有用模块

I: 内置与第三的模块拿来就用,无需定义,这种拿来主义,可以极大地提升自己的开发效率
II: 自定义的模块
可以将程序的各部分功能提取出来放到一模块中为大家共享使用
好处是减少了代码冗余,程序组织结构更加清晰

如何用模块

1、首次导入模块会发生3件事
    1、执行foo.py
    2、产生foo.py的名称空间,将foo.py运行过程中产生的名字都丢到foo的名称空间中
    3、在当前文件中产生的有一个名字foo,该名字指向2中产生的名称空间
之后的导入,都是直接引用首次导入产生的foo.py名称空间, 不会重复执行代码


2、引用:
	print(foo.x)
	print(foo.get)
	print(foo.change)

强调1:模块名.名字,是指名道姓地问某一个模块要名字对应的值,不会与当前名称空间中的名字发生冲突
	x = 1111111111111
	print(x)
	print(foo.x)

强调2:无论是查看还是修改操作的都是模块本身,与调用位置无关

	x = 3333333333
	# foo.get()
	
	foo.change()
	print(x)
	
	print(foo.x)
	foo.get()


可以以逗号为分隔符在一行导入多个模块,不建议在一行同时导入多个模块

导入模块的规范
	I. python内置模块
	II. 第三方模块
	III. 程序员自定义模块


5、import 。。。 as 。。。

6、模块是第一类对象

7、自定义模块的命名应该采用纯小写+下划线的风格

8、可以在函数内导入模块
def func():
    import foo

作业

1、文件内容如下,标题为:姓名,性别,年纪,薪资
    egon male 18 3000
    alex male 38 30000
    wupeiqi female 28 20000
    yuanhao female 28 10000

要求:
从文件中取出每一条记录放入列表中,
列表的每个元素都是{'name':'egon','sex':'male','age':18,'salary':3000}的形式

2 根据1得到的列表,取出薪资最高的人的信息
3 根据1得到的列表,取出最年轻的人的信息
4、将names=['egon','alex_sb','wupeiqi','yuanhao']中的名字全部变大写

5、将names=['egon','alex_sb','wupeiqi','yuanhao']中以sb结尾的名字过滤掉,然后保存剩下的名字长度

6、求文件a.txt中最长的行的长度(长度按字符个数算,需要使用max函数)

7、求文件a.txt中总共包含的字符个数?思考为何在第一次之后的n次sum求和得到的结果为0?(需要使用sum函数)

8、思考题

with open('a.txt') as f:
    g=(len(line) for line in f)
print(sum(g)) #为何报错?
9、文件shopping.txt内容如下

mac,20000,3
lenovo,3000,10
tesla,1000000,10
chicken,200,1
求总共花了多少钱?

打印出所有商品的信息,格式为[{'name':'xxx','price':333,'count':3},...]

求单价大于10000的商品信息,格式同上

10、思考:判断下述说法是否正确
    题目1:
    1、应该将程序所有功能都扔到一个模块中,然后通过导入模块的方式引用它们
    2、应该只将程序各部分组件共享的那一部分功能扔到一个模块中,然后通过导入模块的方式引用它们

    题目2:
    运行python文件与导入python文件的区别是什么?
    运行的python文件产生的名称空间何时回收,为什么?
    导入的python文件产生的名称空间何时回收,为什么?
原文地址:https://www.cnblogs.com/zdw20191029/p/14553352.html