上周复习:

函数的递归调用

函数调用时函数嵌套调用的一种特殊形式

函数在调用时,直接或间接调用了自身,就是梯归调用.

直接调用自身

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

间接调用函数

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

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

递归应该分为两个明确的阶段,回溯与递推. 回溯就是从外向里一层一层递归调用下去,回溯阶段必须要有一个明确地结束条件,每进入下一次递归时,问题的规模都应该有所减少(否则,单纯地重复调用自身是毫无意义的)

递推就是从里向外一层一层结束递归

例子

# 梯归  5个人猜年龄  每个人都是比前一个大2,第5个30


def age(a):
   if a == 5:
       return 30
   return age(a+1)-2
res = age(1)
print(res)
二分
算法:高效率解决问题的方法
二分法必须基于一个有序的容器类型,容器类型里面的数字必须有大小顺序
判断某个值在不在列表内

每次截取上一次容器类型一半进行比较

l = [1,2,3,45,67,90,123,234,689,990...]
target_num = 980
middle_index = l//2
# 利用列表的切片操作截取 小列表
例子
a = [1,2,3,5,7,9,10,32,42,50,64,72,80,94,99,101,]

# 效率低
# num = 5
# for i in a:
#     if i == 5:
#         print('find')
target_num = 72
def get_num(a,target_num):
   if not a:
       print('')
   # 得到中间的索引
   zhong_index = len(a) // 2
   #     判断中间的数字和要得到的数字是否一致
   if target_num > a[zhong_index]:
       num_right = a[zhong_index + 1:]
   #         在递归调用get_num函数
       get_num(num_right,target_num)
   elif target_num <a[zhong_index]:
       left_num = a[0:zhong_index]
       get_num(left_num,target_num)
   else:
       print('找',zhong_index)
   get_num(a,target_num)
三元表达式

三元表达式的应用场景只推荐只有两种的情况的可能下使用

三元表达式固定表达式
   值1 if 条件 else 值2
       条件成立 值1
       条件不成立 值2
x = 1
y = 2
res = x if x > y else y
结果1 if 条件 else 结果2
条件成立返回结果1
条件不成立返回结果2
如果if后面的条件成立返回if前面的值 否则返回else后面的值

例子

is_free = input(>>>:)
is_free = '免费' if is_free == 'y' else '收费'
列表/字典/集合生成式
a = ['tank','owen','egon','nick','seam']
aa = []
for name in a:
   aa.append('%s_sb'%name)
   print(aa)
print(aa)
res1 = ['%s_qw'%name for name in a]
print(res1)
a2 = ['tank_qw', 'owen_qw', 'egon_qw', 'nick_qw', 'seam_qw','we_we']
res2 = [name for name in a2 if name.endswith('_qw')]
# 先for循环依次取出列表里面的每一个元素
# 然后交由if判断 条件成立才会交给for前面的代码
# 如果条件不成立 当前的元素 直接舍弃
q = ['name','password','hobby']
q1 = ['owen','123','read']

dic = {}
for i ,o in enumerate(q):
   print(i,o)
   # print(i , o)
   dic[o] = q1[i]
   print(dic)
print(2222)
res3 = {q:a for q,a in enumerate(q)}
print(res3)
l1 = [i for i in range(10)]
l2 = [i for i in range(10) if i != 4]  # 注意只能跟if不能再跟else了
匿名函数

没有名字的函数

匿名函数通常不会单独使用,是配合内置函数一起使用的

匿名函数的特点:

临时存在用完就没了

关键字:

lambda

lambda 形参:返回值
1.当场定义当场调用
          (lambda 形参:返回值)()
2.给匿名命名
           func = lambda x:x**2
           func()
3.匿名函数通常都是配合其他函数(内置函数,自定义函数)一起使用

例子

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

# :左边的相当于函数的形参
# :右边的相当于函数的返回值
常用的内置函数
max:内部基于for循环,先一个个将传入的容器类型中的元素一个个取出
   当你没有指定key(key对应的是一个函数)的时候 就按照for循环取出来的值比较大小
   如果指定了key,那么max会将元素交给这个函数,拿着该函数返回结果来做大小比较
 

max:最大

d = {
   'jason': 1000,
   'egon': 888888888,
   'tank': 300000,
   'nick': 400000,
}


def func(name):
   return d[name]

print(max(d))
print(max(d, key=func))
print(max(d, key=lambda name: d[name]))

min:最小

min:
d = {
   'jason': 1000,
   'egon': 888888888,
   'tank': 300000,
   'nick': 400000,
}


def func(name):
   return d[name]

print(min(d))
print(min(d, key=func))
print(min(d, key=lambda name: d[name]))

zip:拉链

zip 拉链  # 基于for循环
l1 = [1,2,]
l2 = ['jason','egon','tank']
l3 = ['a','b','c']
print(list(zip(l1,l2,l3)))
# 基于for循环

map:映射

map:映射
l = [1,2,3,4,5,6]
# print(list('hello'))
print(list(map(lambda x:x+5,l)))
# 基于for循环

filter:过滤

l = [1,2,3,4,5,6]
print(list(filter(lambda x:x != 3,l)))  
# 基于for循环

sorted:排序

l = ['jason','egon','nick','tank']
print(sorted(l,reverse=False))

reducel:合并

from functools import reduce
l = [1,2,3,4,5,6]
print(reduce(lambda x,y:x+y,l,19))
# 19初始值 为第一个参数
# 当初始值不存在的情况下 按照下面的规律
# 第一次先获取两个元素 相加
# 之后每次获取一个与上一次相加的结果再相加
无参装饰器
from functools import wraps
def outter(func):
   @wraps(func)
   def inner(*args,**kwargs):  # * **在形参中使用
       # 执行被装饰函数之前你可以做的操作
       res = func(*args,**kwargs)  # * **在实参中使用
       # 执行被装饰函数之后你可以做到操作
       return res
   return inner

@outter
def index(username,*args,**kwargs):
   """index注释"""
   pass
print(index)
装饰器修复技术
1.返回原来的函数的函数名
2.返回原来的函数的注释
from functools import wraps
@wraps(func)
有参装饰器
def wrappers(data):
  # data = 'file'
  def outter(func):
      def inner(*args,**kwargs):
          if data == 'file':
              # 执行被装饰函数之前你可以做的操作
              res = func(*args,**kwargs) # * **在实参中使用
              # 执行被装饰函数之后你可以做到操作
              return res
      return inner
  return outter
今日内容
  迭代器
  可迭代对象
  迭代器对象
  for循环内部原理
  生成器
  面试题
  生成器表达式
  内置函数
  面向过程编程

day13

迭代器

迭代:是一个重复的过程,每次重复即一个迭代,并且每次重复的结果都是下一次迭代的初始值

为什么用迭代:

序列类型:字符串、列表、元组,可以使用索引的方式迭代取出其包含的元素。但对于字典、集合、文件等类型是没有索引的,而提供了一种不依赖索引取值的方法

n = 0
while True:
print(n)
不算,只是单纯的重复
s = 'hello word'
count=0
while count < len(s): #迭代
   print(s[count])
   count +=1
可迭代对象

可迭代对象指的是内置有__iter__方法的对象,即__obj__.

可迭代对象执行obj.__iter__()得到的结果就是迭代器对象
基本数据类型中
  是可迭代对象的有
      str list tuple dict set
      文件对象(执行内置的__iter__之后还是本身 没有任何变化):文件对象本身就是迭代器对象
       
迭代器对象
迭代器对象指的是即内置有__iter__又内置有__next__方法的对象

文件类型是迭代器对象
open('a.txt').__iter__()
open('a.txt').__next__()
迭代器对象无论执行多少次__iter__方法得到的还是迭代器对象本身

例子

i = 1
f = 1.2
s = 'hello'
l = [1,2,3,]
t = (1,2,3)
set = {1,2,3,4}
d = {'name':'abo','password':1230}
f1 = open('a.txt','r',encoding='utf=8')
s.__iter__()
l.__iter__()
t.__iter__()
a1 = d.__iter__()
print(a)
#也可以简化成
res = iter(d)
f1.__iter__()
f1.__next__()

迭代器取值

l =[1,2,3,4,5,6,7,8,9,]
# 生成一个迭代器对象
# iter_l = l.__iter__()
iter_l = iter(l)
# 迭代器对象取值 调用__next__的方法
print(iter_l.__next__())
print(iter_l.__next__())
print(iter_l.__next__())
print(iter_l.__next__())
print(iter_l.__next__())
print(iter_l.__next__())
print(iter_l.__next__())
print(iter_l.__next__())
print(iter_l.__next__())
print(iter_l.__next__())
print(iter_l.__next__())
print(iter_l.__next__())
#报错是因为将值取完了,没有值可以取 报错StopIteration
d = {'name':'obao','password':'123','hobby':'eat'}
#生成一个迭代器对象
iter_d = d.__iter__()
#迭代器对象的取值必须用__naxt__的方法
#print(iter_d.__next__())
#print(iter_d.__next__())
#print(iter_d.__next__())
#print(iter_d.__next__())   # 取完了 报错StopIteration
捕获异常
while True:
   try:
       print(iter_d.__next__())
   except StopIteration:
       print('无值')
       break

迭代器对象一定是可迭代对象,而可迭代对象不一定是迭代对象.

迭代器取值的特点:

优点:

  1. 提供一种统一的、不依赖于索引的迭代方式

  2. 惰性计算,节省内存

缺点:

1.只能往后依次取值 不能往前退

2.无法获取长度,不能获取指定的长度

for循环内部原理
for循环内部的本质
   1.将in后面的对象调用__iter__转换成迭代器对象
   2.调用__next__迭代取值
   3.内部有异常捕获StopIteration,当__next__报这个错 自动结束循环
l = [1,2,3,4]
for i in l:
   print(i)
a = [1,2,3,4]
# for i in a:
#     print(i)
# print(len(a))
res = map(lambda x:x+1,a)
# a = list(map(lambda x:x+10,a))
print(a)
print(res.__next__)
生成器

用户自定义的迭代器,本质就是迭代器.

def func():
   print(11111)
   yield  # 函数内如果有yield关键字,那么加括号执行函数的时候并不会触发函数体代码的运行
# 写出1,100之间的奇数
for i in range(1,100,2)
print(i)
   
   
def my_range(start,end,step=1):
   while start < end:
       yield start
       start += step

for j in my_range(1,100,2):
print(j)

yield支持外界为其传参

def people(name):
   print('%s 准备吃'%name)
   while True:
       food = yield
       print('%s吃了%s'%(name,food))

#当函数内有yield关键字的时候,调用该函数不会执行函数体代码
# 而是将函数变成生成器
a = people('bobo')
a.__next__()    # 必须先将代码运行至yield 才能够为其传值
a.send('包子')   # 给yield左边的变量传参 触发了__next__方法
a.send('饺子')
yield
   1.帮你提供了一种自定义生成器方式
   2.会帮你将函数的运行状态暂停住
   3.可以返回值

与return之间异同点
   相同点:都可以返回值,并且都可以返回多个
   不同点:
       yield可以返回多次值,而return只能返回一次函数立即结束
       yield还可以接受外部传入的值
生成器表达式
res = (i for i in range(1,10)if i!= 3)
# 生成器表达式
"""
生成器不会主动执行任何一行代码
必须通过__next__触发代码的运行
"""
print(res)
print(res.__next__())
print(res.__next__())
print(res.__next__())

应用场景:

1.要在一个很大的容器中获得值

res = (i for i in range(1,100000000) if i != 4)  # 生成器表达式
print(res)
print(res.__next__())
print(res.__next__())
print(res.__next__())

2.统计字符个数

# 占内存
f = open('xxx.txt','r',encoding='utf-8')
data = f.read()
print(len(data))
f.close()


with open('xxx.txt','r',encoding='utf-8') as f:
   # n = 0
   # for line in f:
   #     n += len(line)
   # print(n)
   g = (len(line) for line in f)
   # print(g.__next__())
   # print(g.__next__())
   # print(g.__next__())
   # print(g.__next__())
   print(sum(g))
面试题;

生成器表达式

def add(n,i):
   return n+i
def test():
   for i in range(4):
       yield i
g=test()

for n in [1,10]:
   g=(add(n,i) for i in g)
   # 第一次for循环g=(add(n,i) for i in test())

   # 第二次for循环g=(add(n,i) for i in (add(n,i) for i in test()))
print(n)
res=list(g)

"""
for i in (add(10,i) for i in test()): 会执行所有的生成器内部的代码
  add(n,i)
"""




#A. res=[10,11,12,13]
#B. res=[11,12,13,14]
#C. res=[20,21,22,23] 答案
#D. res=[21,22,23,24]

 

 

内置函数

abs:求平均值

print(abs(-11.11)

all,any

print(all(l))  # 只要有一个为False就返回False
print(any(l))  # 只要有一个位True就返回True

locals,globals

def index():

   username = '我是局部名称空间里面的username'
   # print(locals()) # 当前语句在哪个位置 就会返回哪个位置所存储的所有的名字
   print(globals())  # 无论在哪 查看的都是全局名称空间
index()

bin,oct,hex

print(bin(10))
#转换成二进制
print(oct(10))
#转换成八进制
print(hex(10))
#转换成十六进制
print(int('0b1010',2))
# 转换为整数

bool True,False

print(bool(1))
print(bool(0))

bytes :转换二进制字符

s = 'hello'
print(s.encode('utf-8'))
print(bytes(s,encoding='utf-8'))

callable:可被加括号调用的执行相应功能的

l = [1,2,3]
def index():
   pass
print(callable(l))
print(callable(index))

chr,ord

print(chr(97))  # 将数字转换成ascii码表对应的字符
print(ord('a'))  # 将字符按照ascii表转成对应的数字

dir:dir获取当前对象名称空间里面的名字

l = [1,2,3]
print(dir(l))

import test
print(dir(test))
print(test.name)

divmod:分页器

print(divmod(101,10))
total_num,more = divmod(900,11)
if more:
   total_num += 1
print('总页数:',total_num)

enumerate:枚举

l = ['a','b']
for i,j in enumerate(l,1):
   print(i,j)

eval,exec

s = """
print('hello baby~')
x = 1
y = 2
print(x + y)

"""
# eval(s)
exec(s)
# eval不支持逻辑代码,只支持一些简单的python代码
# exec解释并执行字符串,

format

# {}占位
# {index} 索引
# {name} 指名道姓

help:帮助

def login():
   """
  一起嗨皮
  :return:
  """
print(help(login))

isinstance:后面统一改方法判断对象是否属于某个数据类型

n = 1
print(type(n))
print(isinstance(n,list))  # 判断对象是否属于某个数据类型
print(pow(2,3))
相当于2**3,如果是pow(2, 3, 5),相当于2**3 % 5
print(round(3.4))
# 四舍五入取整
面试过程编程

面向过程是一种编程思路、思想,而编程思路是不依赖于具体的语言或语法的。言外之意是即使我们不依赖于函数,也可以基于面向过程的思想编写程序

面向过程编程:就类似于设计一条流水线
   好处:
       将复杂的问题流程化 从而简单化
   坏处:
       可扩展性较差   一旦需要修改 整体都会受到影响

例子:

# 注册功能
# 1.获取用户输入
def get_info():
   while True:
       username = input(">>>:").strip()
       if not username.isalpha():  # 判断字符串不能包含数字
           print('不能包含数字')
           continue
       password = input('>>>:').strip()
       confirm_password = input("confirm>>>:").strip()
        if password == confirm_password:
operate_data(username,password)
               break
       else:
           print('两次密码不一致')

# 2.处理用户信息
def operate_data(username,password):
   # jason|123
   res = '%s|%s\n'%(username,password)
   save_data(res,'userinfo.txt')

# 3.存储到文件中
def save_data(res,file_name):
   with open(file_name,'a',encoding='utf-8') as f:
       f.write(res)

def register():
   get_info()

register()
def get_info():
   while True:
       username = input(">>>:").strip()
       if not username.isalpha():  # 判断字符串不能包含数字
           print('不能包含数字')
           continue
       password = input('>>>:').strip()
       confirm_password = input("confirm>>>:").strip()
       if password == confirm_password:
           d = {
               '1':'user',
               '2':'admin'
          }
           while True:
               print("""
                  1 普通用户
                  2 管理员
              """)
               choice = input('please choice user type to register>>>:').strip()
               if choice not in d:continue
               user_type = d.get(choice)
               operate_data(username,password,user_type)
               break
       else:
           print('两次密码不一致')

# 2.处理用户信息
def operate_data(username,password,user_type):
   # jason|123
   res = '%s|%s|%s\n'%(username,password,user_type)
   save_data(res,'userinfo.txt')

# 3.存储到文件中
def save_data(res,file_name):
   with open(file_name,'a',encoding='utf-8') as f:
       f.write(res)

def register():
   get_info()

register()
面试题:
   请写出一下代码的执行结果并解释。
def multipliers():

   return [lambda x:i*x for i in range(4)]

   print([m(2) for m in multipliers()])
   
   #0,1,2,3
   # [func(x): return 0*x, func(x): return 1*x,
   # func(x): return 2*x, func(x): return 3*x, ]
   # [func(x): return 0*2, func(x): return 1*2,
# func(x): return 2*2, func(x): return 3*2, ]

# 闭包函数的延迟绑定
# 在内层函数执行时才会绑定变量i
def a2():
   list1 = []
   for i in range(4):

       def func(x):

           return x * i

       list1.append(func)

   return list1

print([m(2) for m in as2()])
# [6, 6, 6, 6]  
   
def multipliers():

   return [lambda x, i=i: i*x for i in range(4)]
   # 0, 1, 2, 3
   # [func(x): return 0*x, func(x): return 1*x,
   # func(x): return 2*x, func(x): return 3*x, ]

print([m(2) for m in multipliers()])  # [0, 2, 4, 6]

# [func(x): return 0*2, func(x): return 1*2,
# func(x): return 2*2, func(x): return 3*2, ]
# [0, 2, 4, 6]


# 闭包函数的延迟绑定
# 在内层函数执行时才会绑定变量i
def multipliers():
   list1 = []
   for i in range(4):

       def func(x, i=i):

           return x * i

       list1.append(func)

   return list1

print([m(2) for m in multipliers()])  # [0, 2, 4, 6]
'''
需求: 读取一个文件并返回每行数据的长度
'''

with open('test1.txt', 'w', encoding='utf-8') as f:
   for line in range(1000):
       f.write(f'www{line}aaa' * (line + 1) + '\n')


# 列表推导式: 处理数据量大的文件会导致内存溢出.
res = [len(line) for line in open('test1.txt', 'r', encoding='utf-8')]
# print(res)


# 生成器表达式: 处理数据量大的文件推荐使用.
res2 = (len(line) for line in open('test1.txt', 'r', encoding='utf-8'))
print(res2)  # <generator object <genexpr> at 0x000002B3748FD0A0>
print(next(res2))
print(next(res2))
# <gen..>1 (0, 1, 2, 3)

g = demo()

g1 = (i for i in g)  # <gen..>2 (0, 1, 2, 3)
g2 = (i for i in list(g1)) # []

print(list(g))  # []
print(list(g1))  # []
print(list(g2))  # [0, 1, 2, 3]



# g,g1,g2里面的值都是指向同一个内存地址.

真实结果:
  [0, 1, 2, 3]
  []

 

posted on 2019-07-15 22:17  我只想你  阅读(240)  评论(0编辑  收藏  举报