学习python-Day17


昨日内容回顾

一、多层装饰器

'语法糖:将紧挨着语法糖的函数名作为参数,传递给@符号后面的函数名。大致效果就是谁靠近,谁就先修饰!'

def outer1(func1):
    print('加载outer1')
    def inner2(*args, **kwargs)
         print('执行inner1')
         return func1(*args, **kwargs)
    return inner1   


def outer2(func2):
    print('加载outer2')
    def inner2(*args, **kwargs)
         print('执行inner2')
         return func2(*args, **kwargs)
    return inner2

def outer3(func3):
    print('加载outer3')
    def inner3(*args, **kwargs)
         print('执行inner3')
         return func3(*args, **kwargs)
    return inner3
@outer1
@outer2
@outer3  
def index():
    print('index!!!')

index()

也可以理解成  index = outer(outer2(outer3(index)))

二、有参装饰器

def outer1(a,b,c):
    def outer(func_name):
        def inner(*args,**kwargs):
            res = func_name(*args,**kwargs)
            return res
        return inner
	 return outer
 @outer1(1,2,3)  # outer(1,2,3)  @outer  index = outer(index)
def index():
    print('from index')
  
'''
注意::  最外层outer1形参写成 outer1(*args,**kwargs),写没问题,但是使用的时候会冲突,需要改变*和**后面的变量名,outer1(*a,**k)

专门针对有形参的情况下 :

问题2(掌握):  内层inner函数的形参是否可以改写为下面的方式
	def inner(user_id,*args,**kwargs):
		func_name(user_id,*args,**kwargs)
	可以,因为单独将user_id拿出来,是为了后面单独多次重复使用这个参数。
	可以将user_id和name、pwd分开,还有这是被修饰对象所需要的参数。
	'''

@outer(1,2,3)
def func(user_id,name,pwd):
    pass

三、递归函数

函数直接或间接代用直接。
递归两个要求:1.每次递归都比上次简单,更接近结果。2.最后有明确的结果。
两个特征:
	1.递归   
    2.回溯   return  


四、算法之二分法

  1. 什么是算法?解决问题的方法

  2. 二分法

    数据是排好序的。
    就是取列表中间位置的数,与要查找的数作比较。大则目标数在左半侧,小则目标数在右半侧。然后在各半侧在从中间找的数与目标数做比较。以此类推,逐渐靠近要找的目标数。
    
  3. 冒泡

    冒泡排序是一种简单的排序算法,它也是一种稳定排序算法。
    原理是重复扫描待排序序列,并比较每一对相邻的元素,当该对元素顺序不正确时进行交换。一直重复这个过程,直到没有任何两个相邻元素可以交换,就表明完成了排序。
    
  4. 快拍

    快速排序算法通过多次比较和交换来实现排序。
    1.首先设定一个分界值,通过该分界值将数组分成左右两部分。
    2.将大于或等于分界值的数据集中到数组右边,小于分界值的数据集中到数组的左边。
    3.左边和右边的数据可以独立排序。对于左侧的数组数据,又可以取一个分界值,将该部分数据分成左右两部分,同样在左边放置较小值,右边放置较大值。右侧的数组数据也可以做类似处理。
    
  5. 插入

    1.用插入算法时一般将数据分为两组,有序组和无序组,并且将数据的第一个元素默认为有序组,将无序组的元素一个一个按照某种排列方式插入到有序组中。
    '''有如下一组数据:1,7,2,6,。我们将这组数据从小到大进行排列'''
    2.有序组默认为有序组第一个元素,1 与余下无序组7,2,6 的比较。将有序组最后一个元素和无序组第一个元素比较,如果后者大,则放到有序组后面位置。[1,7],[2,6]如果小,则需要从有序组由右往左比较,让这个较小元素插入有序组合适的位置。[1,2,7],[6]
    

    有点像斗地主整理牌的思路。

  6. 推排

  7. 桶排

今日学习内容

一、三元表达式

主要就是减少了代码行数

'开始缩短单横的条件语句'
1.获取用户输入的用户名,如果是xz就打印欢迎,否则打印抱歉!
username = input('username>>>:').strip()
if username == 'xz':print('欢迎')
else:print('抱歉!')
'三元表达式:仅限于二选一情况(if...else)并且不建议嵌套使用'
2.编写一个函数,比较两个数的大小,返回大的那个
def my_max(a,b):
    # if a >b:
    #	return a
    # else:
    #	return b
    return a if a > b else b
res = my_max(1, 10)
print(res)

3.#都为True,第一返回后面的,第二返回前面的。
print('哈哈' if 0 else '嘿嘿')
print('嚯嚯' if 1 else '哼哼')

'运行结果:
    嘿嘿
    嚯嚯'

4.
username = input('username>>>:').strip()
if username == 'xz':print('欢迎')
else:print('抱歉')
'上面可以再减少行数!!!!'
print('欢迎') if username == 'xz' else print('抱歉')

5.'三元表达式不适合在嵌套里面使用,会让代码越来复杂'
res = 123 if 10 > 5 else (222 if 0 else (666 if 1 == 2 else 666))

'''
三元表达式语法结构
	值1 if 条件 else 值2
如果if后面的条件成立,则使用if前面的值
如果if后面的条件不成立,则使用else后面的值
'''

注意:在python代码中不是越少越好,还要保证代码的可读性!!!

二、各种生成式

  1. 列表生成式

    name_list = ['xz', 'wyb', 'bx', 'yyds']
    #给上述列表所有的数据值加上s的后缀
    #1.定义一个新的列表
    new_list = []
    #2.循环将原列表所有的数据值取出来
    for name in name_list:
        #3.将取出的数据值拼接一个 s
        new_name = name + 's'
        #再把拼接好的名字再添加到新的列表中
        new_list.append(new_name)
    print(new_list)
    
    '运行结果:
        ['xzs', 'wybs', 'bxs', 'yydss']'
        
    
    '可以将上述的代码弄成 一行代码 的 列表生成式 '
    
    #先执行for循环,然后将一个个的数据值交给for循环前面的拼接处理,最后在整理成一个新列表。
    new_list = [name + 's' for name in name_list ]
    print(new_list)
    
    # 先执行for循环,然后后将一个个数据值交给if去判断, 结果为True则最后交给for循环前面的拼接处理。
    
    new_list = [name + 's' for name in name_list if name != 'xz']
    print(new_list)
    
    '运行结果:
        ['wybs', 'bxs', 'yydss']'
    
    注意:列表生成式中只能出现for和if!!!!不能再后面添加else,系统没法识别else到底属于哪层。
    
  2. 字典生成式

    #for循环将i作为K值,然后将每个k值循环到后面的if判断,当i 为6 时为True,将i为6 的k值,xz为v值放到这个字典中。
    new_dict = {i: 'xz' for i in range(10) if i == 6}
    print(new_dict) #{6:'xz'}
    
  3. 集合生成式

      #将i从0 到 10 for循环一个个取出,交给后面if判断,如果i 为6,则将i为6 放到这个集合中。
      new_set = {i for i in range(10) if i == 6}
      print(new_set) 
    
  4. 元组

    new_tuple = (i for i in range(10))
    print(new_tuple)   at 0x000001E62B8ED740>
    
    注意:元组没有所谓的生成式,它是后面重点讲解的迭代器知识(生成器)
    

三、匿名函数

  1. 匿名函数就是没有函数名的函数

  2. 语法结构:

    ? lambda 形参 : 返回值

    ? eg:

    ? 直接调用(lambda x : x + 1)(123)

    ? 命名调用res = lambda x : x + 1

  3. 应用场景:

    ? 匿名函数通常需要配合其他函数一起使用,用于减少代码。

四、匿名集合内置函数的使用

max()  # 求最大值
l1 = [1,2,3,4,5]
res = max(l1)
print(res)  # 5
#用内置函数可以快速的求出结果。
dict1 = {
    'jason': 100,
    'aj': 123,
    'Bason': 9999,
    'zero': 888
}

#方式一:直接用函数
#传入一个形参K
def index(k):
    #得到K值对应的(V)数据值并其返回
    return dict1.get(k)
#key相当于将index的返回值拿过来给前面的dict1,这里前面的dict1,相当于 for 循环key里面数据值。
res = max(dict1, key = index)
print(res)

#方式二:用匿名函数
#lambda 后面的K表示形参,冒号后面表示字典按k取值将每个数据值取出,然后返回给 key 每个数据值。然后dict1将每个key 的数据值用for循环取出最大值!!!
res = max(dict1, key = lambda k: dict1.get(k))
print(res)


补充:字符串可以做比较。按字符编码表来比较。
	A-Z  65-90
    a-z  97-122

五、重要的内置函数

min()  #最小值
'方法返回字符串中最小的字母'

map()  #映射
'会根据提供的函数对指定序列做映射'
	函数语法:
map(function, iterable, ...)

l1 = [11, 22, 33, 44, 55, 66]
# 需求:将列表中所有的数据值自增20
# 方式1:for循环
new_list = []
for i in l1:
    i += 10
    new_list.append(i)
print(new_list)

# 方式2:列表生成式
new_list = [i+10 for i in l1]
print(new_list)
# 方式3:map函数
res = map(lambda i : i + 10, l1)
print(res)  # 
#python3中map()返回iterators类型,不再是list类型。进行list转换就可以了。
'与 for 循环类似,减少代码函数了'

print(list(res))
def index(a):
    return a + 10
res = map(index, l1)
print(list(res))
filter() #过滤
'函数用于过滤序列,过滤掉不符合条件的元素,返回由符合条件元素组成新的列表'

l1 = ['xz', 'wyb', 'bx', 'yyds']
# 需求:移除数据值里面的yyds


# 方式1:for循环
for i in l1:
    if i == 'yyds':
        l1.remove(i)
print(l1)



# 方式2:列表生成式
#可以用刚刚拼接的方式,for循环内有内置方法的话,可以用if判断i是不是'yyds'。
#如果不是,返回为True,将数据值传入for循环前面的i,yigg放入new_list
new_list = [i for i in l1 if i != 'yyds']
print(new_list) #['xz', 'wyb', 'bx']


#方式3:filter()
res = filter(lambda a: a != 'xz', l1)
print(res)  # 
print(list(res))  #['wyb', 'bx']
def index(a):
    return a != 'xz'
res = filter(index, l1)
print(list(res)) #['wyb', 'bx']

reduce() 
'函数会对参数序列中元素进行累积。'
'''
函数将一个数据集合(链表,元组等)中的所有数据进行下列操作:
用传给 reduce 中的函数 function(有两个参数)先对集合中的第 1、2 个元素进行操作,得到的结果再与第三个数据用 function 函数运算,最后得到一个结果。
'''

l2 = [1, 2, 3]
# 需求:求列表中所有数据值的和
# 方式1:for循环
s = 0
for i in l2:
    s += i
print(s)


# 方式2:sum()
res = sum(l2)
print(res)


# 方式3:reduce()   将很多单体 变成一个整体
from functools import reduce
#用匿名函数,l2后面是可以添加数据值的。
res = reduce(lambda x, y: x + y, l2, 100)
print(res)

#不用匿名函数,直接就是函数。
def index(x,y):
       return x + y
print(res)

zip()
1.函数用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的对象,这样做的好处是节约了不少的内存。
2.可以使用 list() 转换来输出列表。
3.如果各个迭代器的元素个数不一致,则返回列表长度与最短的对象相同,利用 * 号操作符,可以将元组解压为列表。
eg:
    >>> a = [1,2,3]
	>>> b = [4,5,6]
    >>> a1, a2 = zip(*zip(a,b))          
# 与 zip 相反,zip(*) 可理解为解压,返回二维矩阵式
    >>> list(a1)
    [1, 2, 3]
    >>> list(a2)
    [4, 5, 6]
 

#元素根据位置一一对应然后组成一个元组,再用list转化成列表里的元组。
n1 = [1, 2, 3]
n2 = ['xz', 'wyb', 'bx']
res = zip(n1, n2)
print(res)  # 
print(list(res))

'运行结果:
    
    [(1, 'xz'), (2, 'wyb'), (3, 'bx')]'
    
    
#字符串是拆开一个个字符对应。字符串最小单位为一个字符
n1 = [1, 2, 3, 4]
n2 = [5, 6, 7, 8]
n3 = 'wyb'
res = zip(n1, n2, n3)
print(list(res))
'运行结果:
    [(1, 5, 'w'), (2, 6, 'y'), (3, 7, 'b')]'
    

# 元素个数与最短的列表一致
n1 = [1, 2, 3, 4, 5, 6, 7]
n2 = [5, 6, 7, 8]
n3 = 'xz'
res = zip(n1, n2, n3)
print(list(res))

'运行结果:
   [(1, 5, 'x'), (2, 6, 'z')]'

作业

一、多层装饰器

首先,我们要从头开始分析代码开始定义的什么东西。要秉持先定义再调用的概念。我们要明白语法糖的含义。找到语法糖。然后将语法糖的原来的样子写出来。打个备注在旁边。

二、有参装饰器