1.生成器

1.1 初识生成器

什么是生成器?这个概念比较模糊,各种文献都有不同的理解,但是核心基本相同。生成器的本质就是迭代器,在python社区中,大多数时候都把迭代器和生成器是做同一个概念。不是相同么?为什么还要创建生成器?生成器和迭代器也有不同,唯一的不同就是:迭代器都是Python给你提供的已经写好的工具或者通过数据转化得来的,(比如文件句柄,iter([1,2,3])。生成器是需要我们自己用python代码构建的工具。最大的区别也就如此了。

1.2 生成器的构建方式

在python中有三种方式来创建生成器:

  1. 通过生成器函数

  2. 通过生成器推导式

  3. python内置函数或者模块提供(其实1,3两种本质上差不多,都是通过函数的形式生成,只不过1是自己写的生成器函数,3是python提供的生成器函数而已)

1.3 生成器函数

我们先来研究通过生成器函数构建生成器。

首先,我们先看一个很简单的函数:

def func():

    print(11)

    return 22

ret = func()

print(ret)

# 运行结果:

11

22

将函数中的return换成yield,这样func就不是函数了,而是一个生成器函数

def func():
    print(11)
    yield 22

我们这样写没有任何的变化,这是为什么呢? 我们来看看函数名加括号获取到的是什么?

def func():

    print(11)

    yield 22

ret = func()

print(ret)

# 运行结果:

<generator object func at 0x000001A575163888>

运行的结果和最上面的不一样,为什么呢?? 由于函数中存在yield,那么这个函数就是一个生成器函数.

我们在执行这个函数的时候.就不再是函数的执行了.而是获取这个生成器对象,那么生成器对象如何取值呢?

之前我们说了,生成器的本质就是迭代器.迭代器如何取值,生成器就如何取值。所以我们可以直接执行next()来执行以下生成器

def func():

     print("111")

     yield 222

gener = func() # 这个时候函数不会执⾏. ⽽是获取到⽣成器

ret = gener.__next__() # 这个时候函数才会执⾏

print(ret)  # 并且yield会将func生产出来的数据 222 给了 ret。  

结果:

111

222

并且生成器函数中可以写多个yield。

def func():

    print("111")

    yield 222

    print("333")

    yield 444

gener = func()

ret = gener.__next__()

print(ret)

ret2 = gener.__next__()

print(ret2)

ret3 = gener.__next__()

# 最后⼀个yield执⾏完毕. 再次__next__()程序报错

print(ret3)



结果:

111

222

333

444

当程序运行完最后一个yield,那么后面继续运行next()程序会报错,一个yield对应一个next,next超过yield数量,就会报错,与迭代器一样。

    yield与return的区别:

        return一般在函数中只设置一个,他的作用是终止函数,并且给函数的执行者返回值。

        yield在生成器函数中可设置多个,他并不会终止函数,next会获取对应yield生成的元素。

举例:

我们来看一下这个需求:老男孩向楼下卖包子的老板订购了10000个包子.包子铺老板非常实在,一下就全部都做出来了  

def eat():

    lst = []

    for i in range(1,10000):

        lst.append('包子'+str(i))

    return lst

e = eat()

print(e)

这样做没有问题,但是我们由于学生没有那么多,只吃了2000个左右,剩下的8000个,就只能占着一定的空间,放在一边了。如果包子铺老板效率够高,我吃一个包子,你做一个包子,那么这就不会占用太多空间存储了,完美。

def eat():

    for i in range(1,10000):

        yield '包子'+str(i)

e = eat()

for i in range(200):
    next(e)

这两者的区别:

    第一种是直接把包子全部做出来,占用内存。

    第二种是吃一个生产一个,非常的节省内存,而且还可以保留上次的位置。

def eat():

    for i in range(1,10000):

        yield '包子'+str(i)

e = eat()

for i in range(200):
    next(e)
    
for i in range(300):
    next(e)
# 多次next包子的号码是按照顺序记录的。
1.4 send 方法

·接下来我们再来认识一个新的东西,send方法

# next只能获取yield生成的值,但是不能传递值。
def gen(name):
    print(f'{name} ready to eat')
    while 1:
        food = yield
        print(f'{name} start to eat {food}')

dog = gen('alex')
next(dog)
next(dog)
next(dog)


# 而使用send这个方法是可以的。
def gen(name):
    print(f'{name} ready to eat')
    while 1:
        food = yield 222
        print(f'{name} start to eat {food}')

dog = gen('alex')
next(dog)  # 第一次必须用next让指针停留在第一个yield后面
# 与next一样,可以获取到yield的值
ret = dog.send('骨头')
print(ret)


def gen(name):
    print(f'{name} ready to eat')
    while 1:
        food = yield
        print(f'{name} start to eat {food}')

dog = gen('alex')
next(dog)
# 还可以给上一个yield发送值
dog.send('骨头')
dog.send('狗粮')
dog.send('香肠')

send和next()区别:

        相同点:

            send 和 next()都可以让生成器对应的yield向下执行一次。

            都可以获取到yield生成的值。

        不同点:

            第一次获取yield值只能用next不能用send(可以用send(None))。

            send可以给上一个yield置传递值。

1.4 yield from

在python3中提供一种可以直接把可迭代对象中的每一个数据作为生成器的结果进行返回

# 对比yield 与 yield from 
def func():
    lst = ['卫龙','老冰棍','北冰洋','牛羊配']
    yield lst
g = func()
print(g)
print(next(g))  # 只是返回一个列表

def func():
    lst = ['卫龙','老冰棍','北冰洋','牛羊配']
    yield from lst
g = func()
print(g)
# 他会将这个可迭代对象(列表)的每个元素当成迭代器的每个结果进行返回。
print(next(g))
print(next(g))
print(next(g))
print(next(g))
'''
yield from ['卫龙','老冰棍','北冰洋','牛羊配'] 
等同于:
    yield '卫龙'
    yield '老冰棍'
    yield '北冰洋'
    yield '牛羊配'
'''

有个小坑,yield from 是将列表中的每一个元素返回,所以 如果写两个yield from 并不会产生交替的效果

def func():
    lst1 = ['卫龙','老冰棍','北冰洋','牛羊配']
    lst2 = ['馒头','花卷','豆包','大饼']
    yield from lst1
    yield from lst2
    
g = func()
for i in g:
    print(i)

2. 推导式

本节我们讲列表推导式,生成器表达式以及其他推导式,我认为推导式就是构建比较有规律的列表,生成器,字典等一种简便的方式。那么他如何简便呢?看下面的例题:

2.1列表推导式

首先我们先看一下这样的代码,给出一个列表,通过循环,想列表中添加1~10:

li = []

for i in range(10):

    li.append(i)

print(li)

那么按照上面的要求我们用列表推导式写一下:

ls = [i for i in range(10)]

print(ls)

怎么样?一行搞定,上面这个代码就是列表推导式,接下来我们将列表推导式进行一个分类:

列表推导式分为两种模式:

    1.循环模式:[变量(加工的变量) for 变量 in iterable]

    2.筛选模式: [变量(加工的变量) for 变量 in iterable if 条件]

当然还有多层循环的,这个我们一会就会讲到,那么我们先来看循环模式。

2.2 循环模式

刚才我们看到的就是循环模式,那么有同学会问到,什么叫' 加工的变量'? 这个也比较简单,接下来我们做几道题:

  1. 将10以内所有整数的平方写入列表。
l1 = [i*i for i in range(1,11)]
print(l1)
  1. 100以内所有的偶数写入列表.
l1 = [i for i in range(2,101,2)]
print(l1)
  1. 从python1期到python100期写入列表lst
lst = [f'python第{i}期' % i for i in range(1,19)]

print(lst)

上面那个格式化输出的变量f'python{i}',就是加工的变量。

上面做的那三个就是循环模式,比较简单,接下来我们研究筛选模式。

2.3 筛选模式

筛选模式就是在上面的基础上加上一个判断条件,将满足条件的变量留到列表中。

例题:

将这个列表中大于3的元素留下来。

l1 = [4, 3, 2, 6, 5, 5, 7, 8] 

print([i for i in l1 if i > 3])

练习题:

  1. 三十以内可以被三整除的数。
multiples = [i for i in range(30) if i % 3 == 0]
print(multiples)
  1. 过滤掉长度小于3的字符串列表,并将剩下的转换成大写字母
l = ['wusir', 'laonanhai', 'aa', 'b', 'taibai']
# print([i.upper() for i in l if len(i) > 3])
  1. 找到嵌套列表中名字含有两个‘e’的所有名字(有难度
names = [['Tom', 'Billy', 'Jefferson', 'Andrew', 'Wesley', 'Steven', 'Joe'],
         ['Alice', 'Jill', 'Ana', 'Wendy', 'Jennifer', 'Sherry', 'Eva']]

print([name for lst in names for name in lst if name.count('e') >= 2])
2.4 生成器表达式

生成器表达式和列表推导式的语法上一模一样,只是把[]换成()就行了。比如将十以内所有数的平方放到一个生成器表达式中

gen = (i**2 for i in range(10))
print(gen)
# 结果: <generator object <genexpr> at 0x0000026046CAEBF8>

生成器表达式也可以进行筛选

# 获取1-100内能被3整除的数
gen = (i for i in range(1,100) if i % 3 == 0)
for num in gen:
    print(num)

生成器表达式和列表推导式的区别:

  1. 列表推导式比较耗内存,所有数据一次性加载到内存。而.生成器表达式遵循迭代器协议,逐个产生元素。
  2. 得到的值不一样,列表推导式得到的是一个列表.生成器表达式获取的是一个生成器
  3. 列表推导式一目了然,生成器表达式只是一个内存地址。

    无论是生成器表达式,还是列表推导式,他只是Python给你提供了一个相对简单的构造方式,因为使用推导式非常简单,所以大多数都会为之着迷,这个一定要深重,推导式只能构建相对复杂的并且有规律的对象,对于没有什么规律,而且嵌套层数比较多(for循环超过三层)这样就不建议大家用推导式构建。

生成器的惰性机制: 生成器只有在访问的时候才取值,说白了.你找他要才给你值.不找他要.他是不会执行的.

2.5 其他相关的推导式:

    字典推导式

根据名字应该也能猜到,推到出来的是字典

lst1 = ['jay','jj','meet']
lst2 = ['周杰伦','林俊杰','郭宝元']
dic = {lst1[i]:lst2[i] for i in range(len(lst1))}
print(dic)

     集合推导式

集合推导式可以帮我们直接生成一个集合,集合的特点;无序,不重复 所以集合推导式自带去重功能

lst = [1,2,3,-1,-3,-7,9]
s = {abs(i) for i in lst}
print(s)

3. 内置函数

     首先来说,函数就是以功能为导向,一个函数封装一个功能,那么Python将一些常用的功能(比如len)给我们封装成了一个一个的函数,供我们使用,他们不仅效率高(底层都是用C语言写的),而且是拿来即用,避免重复造轮子,那么这些函数就称为内置函数,到目前为止python给我们提供的内置函数一共是68个。

  • 数据类型强制转换
  1. int()转换整形,字符串内容必须是数字
s1 = '123'
s3 = int(s1)
print(s3, type(s3)) # 输出结果:123 <class 'int'>
print(int(3.8)) # 输出结果:3(取整)
  1. str()转换字符串

print(str(转换内容))    #内容任意
  1. bool()转换布尔

print(bool(转换内容)) # 内容为 0 空字符串 空字典 空集合 空元祖 空集合 时为False 其他均为True
  1. list()转换列表 转换对象必须是可迭代的

print(list({'k1': 1}))
print(list('alex'))
print(list((1, 2, 3)))
print(list({1, 2, 3}))
"""
['k1']    # 字典转换对象默认是key
['a', 'l', 'e', 'x']
[1, 2, 3]
[1, 2, 3]
"""
  1. tuple()转换元组转换对象必须是可迭代的

print(tuple({'k1': 1}))
print(tuple('alex'))
print(tuple((1, 2, 3)))
print(tuple({1, 2, 3}))
"""
('k1',)
('a', 'l', 'e', 'x')
(1, 2, 3)
(1, 2, 3)
"""
  1. dict()转换字典

v = dict([("k1","v1"),("k2","v2")])
print(v) # 输出:{'k2': 'v2', 'k1': 'v1'}
s1 = [1, 2, 3]
name = ['alex', 'eric', 'william']
print(dict(zip(s1, name)))  # {1: 'alex', 2: 'eric', 3: 'william'}
print(dict(one=1, two=2))   # {'one': 1, 'two': 2}
  1. set()转换集合转换对象必须是可迭代的

print(set({'k1': 1, 'k2': 2}))
print(set('alex'))
print(set((1, 2, 3)))
print(set({1, 2, 3}))
"""
{'k2', 'k1'}
{'a', 'l', 'e', 'x'}
{1, 2, 3}
{1, 2, 3}
"""
  • 输入输出
  1. input()输入
s = input('>>>')
print(s)
  1. print()输出 sep设定分隔符,默认为空。end 设定换行符,默认为\n换行

''' 源码分析
def print(self, *args, sep=' ', end='\n', file=None): # known special case of print
    """
    print(value, ..., sep=' ', end='\n', file=sys.stdout, flush=False)
    file:  默认是输出到屏幕,如果设置为文件句柄,输出到文件
    sep:   打印多个值之间的分隔符,默认为空格
    end:   每一次打印的结尾,默认为换行符
    flush: 立即把内容输出到流文件,不作缓存
    """
'''
print(111,222,333,sep='*')  # 111*222*333
print(111,end='')
print(222)  #两行的结果 111222
f = open('log','w',encoding='utf-8')
print('写入文件',file=f,flush=True)
  • 数学相关
  1. abs()绝对值
print(abs(-10))     # 输出结果:10
  1. float()浮点型

print(float(3))     # 输出结果:3.0
print(float(123))   # 输出结果:123.0
  1. complex() 用于创建一个值为 real + imag * j 的复数或者转化一个字符串或数为复数。如果第一个参数为字符串,则不需要指定第二个参数

print(complex(1,2))  # 输出结果:(1+2j)
  1. max()最大,可以设置key值,必须是函数名,按照函数返回值进行比较(用法详参min)

  2. min()最小,可以设置key值,必须是函数名,按照函数返回值进行比较


    print(min([1, 2, 3]))  # 返回此序列最小值
    ret = min([1, 2, -5], key=abs)  # 按照绝对值的大小,返回此序列最小值
    print(ret)
    # 加key是可以加函数名,min自动会获取传入函数中的参数的每个元素,然后通过你设定的返回值比较大小,返回最小的传入的那个参数。
    print(min(1, 2, -5, 6, -3, key=lambda x: abs(x)))  # 可以设置很多参数比较大小
    dic = {'a': 3, 'b': 2, 'c': 1}
    print(min(dic, key=lambda x:dic[x]))
    # x为dic的key,lambda的返回值(即dic的值进行比较)返回最小的值对应的键
    l1 = [('alex', 78, 170), ('eric', 45, 160), ('william', 28, 182)]
    print(min(l1, key=lambda x: x[1]))  # ('william', 28, 182)
    print(min(l1, key=lambda x: x[-1])) # ('eric', 45, 160)


  3. sum(可迭代对象,初始值(默认为0))求和


    print(sum([1, 2, 3]))
    print(sum((1, 2, 3), 100))
    print(sum({1: 'alex', 2: 'eric'}))  # 字典的key为数字类型
    print(sum({1, 2, 3}))
    """
    6
    106
    3
    6
    """


  4. divmod()两数相除的商和余数,最多应用于分页查看

user_info_list = []
for i in range(875):
    msg = {'name': 'name%s' % i, 'email': '%s@qq.com' % i}
    user_info_list.append(msg)
max_page_content = 10
pager, a = divmod(len(user_info_list), max_page_content)
if a > 0:
    pager += 1
while True:
    user_choose = int(input('请输入查看页码:'))
    if user_choose < 1 or user_choose > pager:
        print('页码错误,请在1-%s之间选择' % pager)
    else:
        first_content = (user_choose - 1) * max_page_content
        last_content = user_choose * max_page_content
        for item in user_info_list[first_content:last_content]:
            print(item)
  1. pow()求x* *y次幂。(三个参数为x**y的结果对z取余)


    print(pow(2,3))  # 两个参数为2**3次幂
    print(pow(2,3,3))  # 三个参数为2**3次幂,对3取余。


  2. round()四舍五入保留几位小数


    print(round(7/3,2))  # 2.33
    print(round(7/3))  # 2
    print(round(3.32567,3))  # 3.326


  • 进制转换
  1. bin()十进制转换二进制
  2. oct()十进制转换八进制
  3. hex()十进制转换十六进制
  4. int(数据,base=进制)转换十进制
print(bin(56))
print(oct(56))
print(hex(56))
print(int('0b111000', base=2))
print(int('0o70', base=8))
print(int('0x38', base=16))
  • 编码相关
  1. chr()将十进制数字转换成unicode编码中的对应字符
  2. ord()根据字符在Unicode编码中找到对应的数字编号
  • 应用(随机验证码)
import random


def get_random_code(length=6):
    data = []
    for i in range(length):
        data.append(chr(random.randint(65, 90)))
    return ''.join(data)


v = get_random_code()
print(v)
  • 高级内置函数
  1. filter()对序列进行筛选,获取符合条件的序列
  2. map()遍历序列,对序列中的每个元素进行操作,生成新的序列
  3. educe()对序列中的元素进行累计操作
案例(map)

* 第一个参数必须是函数,函数参数一个
* 第二个参数必须是可迭代的(可以for循环)
v1 = [11, 22, 33]
result = map (lambda x:x+100,v1)
print(result)   # py2.x输出[111,122,133] py3.x输出可迭代对象,可以进行list()强制换案例(filter)
案例(filter)

第一个参数必须是函数,函数参数一个

第二个参数必须是可迭代的(可以for循环)

v1 = [11, 22, 'hhh',33]
result = filter (lambda x: type(x)==int,v1)
# result = filter (lambda x:True if type(x)==int else False,v1) #第二种写法
print(result)   # py2.x输出[11,22,33] py3.x输出可迭代对象,可以进行list()强制换案例(filtr)
案例(reduce)

py3.x使用reduce需要先导入模块functools

第一个参数必须是函数,函数参数必须是两个

第二个参数必须是可迭代的(可以for循环)

import functools

v1 = [1, 2, 3, 4]
result = functools.reduce(lambda x, y: x + y, v1)   # 加减乘除都可
print(result)   # 输出结果:10
  • 其他
  1. id()查看内存地址
s1 = 123
print(id(s))    # 输出结果类似于:2414242616752
  1. type()查看数据类型

s1 = 123
print(type(s))  # 输出结果:<class 'int'>
s2 = '123'
print(type(s))  # 输出结果:<class 'str'>
  1. len()计算对象长度

s1 = [1, 2, 3, 4]
print(len(s1))  # 输出结果:4
s2 = 'alexsb'
print(len(s2))  # 输出结果:6
  1. open()打开文件

with open('a.txt', mode='w', encoding='utf-8') as f2:
    pass
f1 = open('a.txt', mode='w', encoding='utf-8')
f1.close()
  1. range()创建数字序列

l1 = [i for i in range(10)]
print(l1)   # 输出结果:[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
  1. reversed()反转一个可迭代对象,返回一个迭代器

s1 = 'alex'
print(reversed(s1)) # <reversed object at 0x0000028B33E98390>
s2 = [1, 2]
print(reversed(s2)) # <list_reverseiterator object at 0x0000028B33E98390>
  1. sorted()排序,形成新数据集合

语法:sorted(iterable,key=None,reverse=False)

iterable : 可迭代对象

key: 排序规则(排序函数),在sorted内部会将可迭代对象中的每一个元素传递给这个函数的参数.根据函数运算的结果进行排序

reverse :是否是倒叙,True 倒叙 False 正序

lst = [1,3,2,5,4]
lst2 = sorted(lst)
print(lst)    #原列表不会改变
print(lst2)   #返回的新列表是经过排序的
 
 
lst3 = sorted(lst,reverse=True)
print(lst3)   #倒叙
 
结果:
[1, 3, 2, 5, 4]
[1, 2, 3, 4, 5]
[5, 4, 3, 2, 1]

字典使用sorted排序

dic = {1:'a',3:'c',2:'b'}
print(sorted(dic))   # 字典排序返回的就是排序后的key
 
结果:
[1,2,3]



和函数组合使用

# 定义一个列表,然后根据一元素的长度排序
lst = ['天龙八部','西游记','红楼梦','三国演义']
 
# 计算字符串的长度
def func(s):
    return len(s)
print(sorted(lst,key=func))
 
# 结果:
# ['西游记', '红楼梦', '天龙八部', '三国演义']


和lambda组合使用

lst = ['天龙八部','西游记','红楼梦','三国演义']
 
print(sorted(lst,key=lambda s:len(s)))
 
结果:
['西游记', '红楼梦', '天龙八部', '三国演义']
 
 
lst = [{'id':1,'name':'alex','age':18},
    {'id':2,'name':'wusir','age':17},
    {'id':3,'name':'taibai','age':16},]
 
# 按照年龄对学生信息进行排序
 
print(sorted(lst,key=lambda e:e['age']))
 
结果:
[{'id': 3, 'name': 'taibai', 'age': 16}, {'id': 2, 'name': 'wusir', 'age': 17}, {'id': 1, 'name': 'alex', 'age': 18}]
  1. zip() 拉链方法,函数用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元祖组成的内容,如果各个迭代器的元素个数不一致,则按照长度最短的返回

lst1 = [1,2,3]
lst2 = ['a','b','c','d']
lst3 = (11,12,13,14,15)
for i in zip(lst1,lst2,lst3):
    print(i)
结果:
(1, 'a', 11)
(2, 'b', 12)
(3, 'c', 13)
  1. hash()获取一个对象的哈希值(int、str、bool、tuple)

print(hash(123))
print(hash('123'))
print(hash('asfr'))
print(hash(True))
print(hash(False))
print(hash((1, 2, 3)))
"""
输出结果:
123
4582654100250779780
3968706218629953014
1
0
2528502973977326415
"""
  1. dir()查看数据类型功能方法

print(dir(list))
print(dir(str))
print(dir(float))
print(dir(set))
  1. bytes() 用于不同编码之间的转换

s = '你好'
bs = s.encode('utf-8')
print(bs)
s1 = bs.decode('utf-8')
print(s1)
bs = bytes(s, encoding='utf-8')
print(bs)
b = '你好'.encode('gbk')
b1 = b.decode('gbk')
print(b1.encode('utf-8'))
"""
输出结果:
b'\xe4\xbd\xa0\xe5\xa5\xbd'
你好
b'\xe4\xbd\xa0\xe5\xa5\xbd'
b'\xe4\xbd\xa0\xe5\xa5\xbd'
"""
  1. enumerate()枚举

    enumerate在字典上是枚举、列举的意思enumerate参数为可遍历/可迭代的对象(如列表、字符串)enumerate多用于在for循环中得到计数,利用它可以同时获得索引和值,即需要index和value值的时候可以使用enumerateenumerate()返回的是一个enumerate对象


    >>> lst = [1,2,3,4,5,6]
    >>> for index,value in enumerate(lst):
      print ('%s,%s' % (index,value))
      
    0,1
    1,2
    2,3
    3,4
    4,5
    5,6
    #指定索引从1开始
    >>> lst = [1,2,3,4,5,6]
    >>> for index,value in enumerate(lst,1):
    print ('%s,%s' % (index,value))
    
    1,1
    2,2
    3,3
    4,4
    5,5
    6,6
    
    #指定索引从3开始
    >>> for index,value in enumerate(lst,3):
    print ('%s,%s' % (index,value))
    
    3,1
    4,2
    5,3
    6,4
    7,5
    8,6


  2. iter()转换为迭代器

  3. next()迭代器取值

s = '12345678'
obj = iter(s)
print(next(obj))
print(next(obj))
print(next(obj))
print(next(obj))
..........              # 取后续值
  1. globals()以字典的形式返回全局作用域所有的变量对应关系。

  2. locals()以字典的形式返回当前作用域的变量的对应关系。

# 在全局作用域下打印,则他们获取的都是全局作用域的所有的内容。
a = 2
b = 3
print(globals())
print(locals())
'''
{'__name__': '__main__', '__doc__': None, '__package__': None,
'__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x000001806E50C0B8>, 
'__spec__': None, '__annotations__': {},
'__builtins__': <module 'builtins' (built-in)>, 
'__file__': 'D:/lnh.python/py project/teaching_show/day09~day15/function.py',
'__cached__': None, 'a': 2, 'b': 3}
'''

# 在局部作用域中打印。
a = 2
b = 3
def foo():
    c = 3
    print(globals()) # 和上面一样,还是全局作用域的内容
    print(locals()) # {'c': 3}
foo()
  1. help() 查看函数或模块的具体使用方法(以列表append方位为例)

print(help(list.append))
"""
输出结果:
append(self, object, /)
    Append object to the end of the list.

None
"""
  1. callable()判断变量是否可调用

name = 'alex'
def func():
    pass
print(callable(name))  # 输出结果:False
print(callable(func))  # 输出结果:True
  1. repr()原形毕露 全部显示尤其''

# %r  原封不动的写出来
# name = 'william'
# print('我叫%r'%name)    # 我叫'william'

# repr 原形毕露
print(repr('{"name":"alex"}'))
print('{"name":"alex"}')
"""
输出结果:
'{"name":"alex"}'
{"name":"alex"}
"""
  1. all()判断可迭代对象中全部元素是否全是真

  2. any()判断可迭代对象中是否有元素为真

print(all([1, 2, True, 0])) # False
print(any([1, '', 0]))  # True
  • 慎用
  1. eval() 剥去字符串外衣,返回里面的本质
s1 = '1+2'
print(s1)   # 1+2
print(eval(s1)) # 3
s2 = "{'name':'alex'}"
print(type(s2)) # <class 'str'>
print(type(eval(s2)))   # <class 'dict'>
  1. exec() 代码流,过程,无返回值

s3 = """
for i in range(3):
    print(i)
"""
exec(s3)    # 0 1 2

4.匿名函数

匿名函数,顾名思义就是没有名字的函数,那么什么函数没有名字呢?这个就是我们以后面试或者工作中经常用匿名函数 lambda,也叫一句话函数。

现在有一个需求:你们写一个函数,此函数接收两个int参数,返回和值。

def func(a,b):
    return a+b
print(func(3,4))

那么接下来我们用匿名函数完成上面的需求:

func = lambda a,b: a+b
print(func(3, 4))  # 7

我们分析一下上面的代码:

语法:

  函数名 = lambda 参数:返回值

    1)此函数不是没有名字,他是有名字的,他的名字就是你给其设置的变量,比如func.

    2)lambda 是定义匿名函数的关键字,相当于函数的def.

    3)lambda 后面直接加形参,形参加多少都可以,只要用逗号隔开就行。

func = lambda a,b,*args,sex= 'alex',c,**kwargs: kwargs
print(func(3, 4,c=666,name='alex'))  # {'name': 'alex'}
# 所有类型的形参都可以加,但是一般使用匿名函数只是加位置参数,其他的用不到。

    4)返回值在冒号之后设置,返回值和正常的函数一样,可以是任意数据类型。

    5)匿名函数不管多复杂.只能写一行.且逻辑结束后直接返回数据

接下来做几个匿名函数的小题:

写匿名函数:接收一个可切片的数据,返回索引为0与2的对应的元素(元组形式)。

func = lambda x:(x[0],x[2])
print(func('afafasd'))
func = lambda x:(x[0],x[2])
print(func('afafasd'))

写匿名函数:接收两个int参数,将较大的数据返回。

func = lambda x,y: x if x > y else y
print(func(3,100))
func = lambda x,y: x if x > y else y
print(func(3,100))




1.1 初识生成器

什么是生成器?这个概念比较模糊,各种文献都有不同的理解,但是核心基本相同。生成器的本质就是迭代器,在python社区中,大多数时候都把迭代器和生成器是做同一个概念。不是相同么?为什么还要创建生成器?生成器和迭代器也有不同,唯一的不同就是:迭代器都是Python给你提供的已经写好的工具或者通过数据转化得来的,(比如文件句柄,iter([1,2,3])。生成器是需要我们自己用python代码构建的工具。最大的区别也就如此了。

1.2 生成器的构建方式

在python中有三种方式来创建生成器:

  1. 通过生成器函数

  2. 通过生成器推导式

  3. python内置函数或者模块提供(其实1,3两种本质上差不多,都是通过函数的形式生成,只不过1是自己写的生成器函数,3是python提供的生成器函数而已)

1.3 生成器函数

我们先来研究通过生成器函数构建生成器。

首先,我们先看一个很简单的函数:

def func():

    print(11)

    return 22

ret = func()

print(ret)

# 运行结果:

11

22

将函数中的return换成yield,这样func就不是函数了,而是一个生成器函数

def func():
    print(11)
    yield 22

我们这样写没有任何的变化,这是为什么呢? 我们来看看函数名加括号获取到的是什么?

def func():

    print(11)

    yield 22

ret = func()

print(ret)

# 运行结果:

<generator object func at 0x000001A575163888>

运行的结果和最上面的不一样,为什么呢?? 由于函数中存在yield,那么这个函数就是一个生成器函数.

我们在执行这个函数的时候.就不再是函数的执行了.而是获取这个生成器对象,那么生成器对象如何取值呢?

之前我们说了,生成器的本质就是迭代器.迭代器如何取值,生成器就如何取值。所以我们可以直接执行next()来执行以下生成器

def func():

     print("111")

     yield 222

gener = func() # 这个时候函数不会执⾏. ⽽是获取到⽣成器

ret = gener.__next__() # 这个时候函数才会执⾏

print(ret)  # 并且yield会将func生产出来的数据 222 给了 ret。  

结果:

111

222

并且生成器函数中可以写多个yield。

def func():

    print("111")

    yield 222

    print("333")

    yield 444

gener = func()

ret = gener.__next__()

print(ret)

ret2 = gener.__next__()

print(ret2)

ret3 = gener.__next__()

# 最后⼀个yield执⾏完毕. 再次__next__()程序报错

print(ret3)



结果:

111

222

333

444

当程序运行完最后一个yield,那么后面继续运行next()程序会报错,一个yield对应一个next,next超过yield数量,就会报错,与迭代器一样。

    yield与return的区别:

        return一般在函数中只设置一个,他的作用是终止函数,并且给函数的执行者返回值。

        yield在生成器函数中可设置多个,他并不会终止函数,next会获取对应yield生成的元素。

举例:

我们来看一下这个需求:老男孩向楼下卖包子的老板订购了10000个包子.包子铺老板非常实在,一下就全部都做出来了  

def eat():

    lst = []

    for i in range(1,10000):

        lst.append('包子'+str(i))

    return lst

e = eat()

print(e)

这样做没有问题,但是我们由于学生没有那么多,只吃了2000个左右,剩下的8000个,就只能占着一定的空间,放在一边了。如果包子铺老板效率够高,我吃一个包子,你做一个包子,那么这就不会占用太多空间存储了,完美。

def eat():

    for i in range(1,10000):

        yield '包子'+str(i)

e = eat()

for i in range(200):
    next(e)

这两者的区别:

    第一种是直接把包子全部做出来,占用内存。

    第二种是吃一个生产一个,非常的节省内存,而且还可以保留上次的位置。

def eat():

    for i in range(1,10000):

        yield '包子'+str(i)

e = eat()

for i in range(200):
    next(e)
    
for i in range(300):
    next(e)
# 多次next包子的号码是按照顺序记录的。
1.4 send 方法

·接下来我们再来认识一个新的东西,send方法

# next只能获取yield生成的值,但是不能传递值。
def gen(name):
    print(f'{name} ready to eat')
    while 1:
        food = yield
        print(f'{name} start to eat {food}')

dog = gen('alex')
next(dog)
next(dog)
next(dog)


# 而使用send这个方法是可以的。
def gen(name):
    print(f'{name} ready to eat')
    while 1:
        food = yield 222
        print(f'{name} start to eat {food}')

dog = gen('alex')
next(dog)  # 第一次必须用next让指针停留在第一个yield后面
# 与next一样,可以获取到yield的值
ret = dog.send('骨头')
print(ret)


def gen(name):
    print(f'{name} ready to eat')
    while 1:
        food = yield
        print(f'{name} start to eat {food}')

dog = gen('alex')
next(dog)
# 还可以给上一个yield发送值
dog.send('骨头')
dog.send('狗粮')
dog.send('香肠')

send和next()区别:

        相同点:

            send 和 next()都可以让生成器对应的yield向下执行一次。

            都可以获取到yield生成的值。

        不同点:

            第一次获取yield值只能用next不能用send(可以用send(None))。

            send可以给上一个yield置传递值。

1.4 yield from

在python3中提供一种可以直接把可迭代对象中的每一个数据作为生成器的结果进行返回

# 对比yield 与 yield from 
def func():
    lst = ['卫龙','老冰棍','北冰洋','牛羊配']
    yield lst
g = func()
print(g)
print(next(g))  # 只是返回一个列表

def func():
    lst = ['卫龙','老冰棍','北冰洋','牛羊配']
    yield from lst
g = func()
print(g)
# 他会将这个可迭代对象(列表)的每个元素当成迭代器的每个结果进行返回。
print(next(g))
print(next(g))
print(next(g))
print(next(g))
'''
yield from ['卫龙','老冰棍','北冰洋','牛羊配'] 
等同于:
    yield '卫龙'
    yield '老冰棍'
    yield '北冰洋'
    yield '牛羊配'
'''

有个小坑,yield from 是将列表中的每一个元素返回,所以 如果写两个yield from 并不会产生交替的效果

def func():
    lst1 = ['卫龙','老冰棍','北冰洋','牛羊配']
    lst2 = ['馒头','花卷','豆包','大饼']
    yield from lst1
    yield from lst2
    
g = func()
for i in g:
    print(i)

2. 推导式

本节我们讲列表推导式,生成器表达式以及其他推导式,我认为推导式就是构建比较有规律的列表,生成器,字典等一种简便的方式。那么他如何简便呢?看下面的例题:

2.1列表推导式

首先我们先看一下这样的代码,给出一个列表,通过循环,想列表中添加1~10:

li = []

for i in range(10):

    li.append(i)

print(li)

那么按照上面的要求我们用列表推导式写一下:

ls = [i for i in range(10)]

print(ls)

怎么样?一行搞定,上面这个代码就是列表推导式,接下来我们将列表推导式进行一个分类:

列表推导式分为两种模式:

    1.循环模式:[变量(加工的变量) for 变量 in iterable]

    2.筛选模式: [变量(加工的变量) for 变量 in iterable if 条件]

当然还有多层循环的,这个我们一会就会讲到,那么我们先来看循环模式。

2.2 循环模式

刚才我们看到的就是循环模式,那么有同学会问到,什么叫' 加工的变量'? 这个也比较简单,接下来我们做几道题:

  1. 将10以内所有整数的平方写入列表。
l1 = [i*i for i in range(1,11)]
print(l1)
  1. 100以内所有的偶数写入列表.
l1 = [i for i in range(2,101,2)]
print(l1)
  1. 从python1期到python100期写入列表lst
lst = [f'python第{i}期' % i for i in range(1,19)]

print(lst)

上面那个格式化输出的变量f'python{i}',就是加工的变量。

上面做的那三个就是循环模式,比较简单,接下来我们研究筛选模式。

2.3 筛选模式

筛选模式就是在上面的基础上加上一个判断条件,将满足条件的变量留到列表中。

例题:

将这个列表中大于3的元素留下来。

l1 = [4, 3, 2, 6, 5, 5, 7, 8] 

print([i for i in l1 if i > 3])

练习题:

  1. 三十以内可以被三整除的数。
multiples = [i for i in range(30) if i % 3 == 0]
print(multiples)
  1. 过滤掉长度小于3的字符串列表,并将剩下的转换成大写字母
l = ['wusir', 'laonanhai', 'aa', 'b', 'taibai']
# print([i.upper() for i in l if len(i) > 3])
  1. 找到嵌套列表中名字含有两个‘e’的所有名字(有难度
names = [['Tom', 'Billy', 'Jefferson', 'Andrew', 'Wesley', 'Steven', 'Joe'],
         ['Alice', 'Jill', 'Ana', 'Wendy', 'Jennifer', 'Sherry', 'Eva']]

print([name for lst in names for name in lst if name.count('e') >= 2])
2.4 生成器表达式

生成器表达式和列表推导式的语法上一模一样,只是把[]换成()就行了。比如将十以内所有数的平方放到一个生成器表达式中

gen = (i**2 for i in range(10))
print(gen)
# 结果: <generator object <genexpr> at 0x0000026046CAEBF8>

生成器表达式也可以进行筛选

# 获取1-100内能被3整除的数
gen = (i for i in range(1,100) if i % 3 == 0)
for num in gen:
    print(num)

生成器表达式和列表推导式的区别:

  1. 列表推导式比较耗内存,所有数据一次性加载到内存。而.生成器表达式遵循迭代器协议,逐个产生元素。
  2. 得到的值不一样,列表推导式得到的是一个列表.生成器表达式获取的是一个生成器
  3. 列表推导式一目了然,生成器表达式只是一个内存地址。

    无论是生成器表达式,还是列表推导式,他只是Python给你提供了一个相对简单的构造方式,因为使用推导式非常简单,所以大多数都会为之着迷,这个一定要深重,推导式只能构建相对复杂的并且有规律的对象,对于没有什么规律,而且嵌套层数比较多(for循环超过三层)这样就不建议大家用推导式构建。

生成器的惰性机制: 生成器只有在访问的时候才取值,说白了.你找他要才给你值.不找他要.他是不会执行的.

2.5 其他相关的推导式:

    字典推导式

根据名字应该也能猜到,推到出来的是字典

lst1 = ['jay','jj','meet']
lst2 = ['周杰伦','林俊杰','郭宝元']
dic = {lst1[i]:lst2[i] for i in range(len(lst1))}
print(dic)

     集合推导式

集合推导式可以帮我们直接生成一个集合,集合的特点;无序,不重复 所以集合推导式自带去重功能

lst = [1,2,3,-1,-3,-7,9]
s = {abs(i) for i in lst}
print(s)

3. 内置函数

     首先来说,函数就是以功能为导向,一个函数封装一个功能,那么Python将一些常用的功能(比如len)给我们封装成了一个一个的函数,供我们使用,他们不仅效率高(底层都是用C语言写的),而且是拿来即用,避免重复造轮子,那么这些函数就称为内置函数,到目前为止python给我们提供的内置函数一共是68个。

  • 数据类型强制转换
  1. int()转换整形,字符串内容必须是数字
s1 = '123'
s3 = int(s1)
print(s3, type(s3)) # 输出结果:123 <class 'int'>
print(int(3.8)) # 输出结果:3(取整)
  1. str()转换字符串

print(str(转换内容))    #内容任意
  1. bool()转换布尔

print(bool(转换内容)) # 内容为 0 空字符串 空字典 空集合 空元祖 空集合 时为False 其他均为True
  1. list()转换列表 转换对象必须是可迭代的

print(list({'k1': 1}))
print(list('alex'))
print(list((1, 2, 3)))
print(list({1, 2, 3}))
"""
['k1']    # 字典转换对象默认是key
['a', 'l', 'e', 'x']
[1, 2, 3]
[1, 2, 3]
"""
  1. tuple()转换元组转换对象必须是可迭代的

print(tuple({'k1': 1}))
print(tuple('alex'))
print(tuple((1, 2, 3)))
print(tuple({1, 2, 3}))
"""
('k1',)
('a', 'l', 'e', 'x')
(1, 2, 3)
(1, 2, 3)
"""
  1. dict()转换字典

v = dict([("k1","v1"),("k2","v2")])
print(v) # 输出:{'k2': 'v2', 'k1': 'v1'}
s1 = [1, 2, 3]
name = ['alex', 'eric', 'william']
print(dict(zip(s1, name)))  # {1: 'alex', 2: 'eric', 3: 'william'}
print(dict(one=1, two=2))   # {'one': 1, 'two': 2}
  1. set()转换集合转换对象必须是可迭代的

print(set({'k1': 1, 'k2': 2}))
print(set('alex'))
print(set((1, 2, 3)))
print(set({1, 2, 3}))
"""
{'k2', 'k1'}
{'a', 'l', 'e', 'x'}
{1, 2, 3}
{1, 2, 3}
"""
  • 输入输出
  1. input()输入
s = input('>>>')
print(s)
  1. print()输出 sep设定分隔符,默认为空。end 设定换行符,默认为\n换行

''' 源码分析
def print(self, *args, sep=' ', end='\n', file=None): # known special case of print
    """
    print(value, ..., sep=' ', end='\n', file=sys.stdout, flush=False)
    file:  默认是输出到屏幕,如果设置为文件句柄,输出到文件
    sep:   打印多个值之间的分隔符,默认为空格
    end:   每一次打印的结尾,默认为换行符
    flush: 立即把内容输出到流文件,不作缓存
    """
'''
print(111,222,333,sep='*')  # 111*222*333
print(111,end='')
print(222)  #两行的结果 111222
f = open('log','w',encoding='utf-8')
print('写入文件',file=f,flush=True)
  • 数学相关
  1. abs()绝对值
print(abs(-10))     # 输出结果:10
  1. float()浮点型

print(float(3))     # 输出结果:3.0
print(float(123))   # 输出结果:123.0
  1. complex() 用于创建一个值为 real + imag * j 的复数或者转化一个字符串或数为复数。如果第一个参数为字符串,则不需要指定第二个参数

print(complex(1,2))  # 输出结果:(1+2j)
  1. max()最大,可以设置key值,必须是函数名,按照函数返回值进行比较(用法详参min)

  2. min()最小,可以设置key值,必须是函数名,按照函数返回值进行比较


    print(min([1, 2, 3]))  # 返回此序列最小值
    ret = min([1, 2, -5], key=abs)  # 按照绝对值的大小,返回此序列最小值
    print(ret)
    # 加key是可以加函数名,min自动会获取传入函数中的参数的每个元素,然后通过你设定的返回值比较大小,返回最小的传入的那个参数。
    print(min(1, 2, -5, 6, -3, key=lambda x: abs(x)))  # 可以设置很多参数比较大小
    dic = {'a': 3, 'b': 2, 'c': 1}
    print(min(dic, key=lambda x:dic[x]))
    # x为dic的key,lambda的返回值(即dic的值进行比较)返回最小的值对应的键
    l1 = [('alex', 78, 170), ('eric', 45, 160), ('william', 28, 182)]
    print(min(l1, key=lambda x: x[1]))  # ('william', 28, 182)
    print(min(l1, key=lambda x: x[-1])) # ('eric', 45, 160)


  3. sum(可迭代对象,初始值(默认为0))求和


    print(sum([1, 2, 3]))
    print(sum((1, 2, 3), 100))
    print(sum({1: 'alex', 2: 'eric'}))  # 字典的key为数字类型
    print(sum({1, 2, 3}))
    """
    6
    106
    3
    6
    """


  4. divmod()两数相除的商和余数,最多应用于分页查看

user_info_list = []
for i in range(875):
    msg = {'name': 'name%s' % i, 'email': '%s@qq.com' % i}
    user_info_list.append(msg)
max_page_content = 10
pager, a = divmod(len(user_info_list), max_page_content)
if a > 0:
    pager += 1
while True:
    user_choose = int(input('请输入查看页码:'))
    if user_choose < 1 or user_choose > pager:
        print('页码错误,请在1-%s之间选择' % pager)
    else:
        first_content = (user_choose - 1) * max_page_content
        last_content = user_choose * max_page_content
        for item in user_info_list[first_content:last_content]:
            print(item)
  1. pow()求x* *y次幂。(三个参数为x**y的结果对z取余)


    print(pow(2,3))  # 两个参数为2**3次幂
    print(pow(2,3,3))  # 三个参数为2**3次幂,对3取余。


  2. round()四舍五入保留几位小数


    print(round(7/3,2))  # 2.33
    print(round(7/3))  # 2
    print(round(3.32567,3))  # 3.326


  • 进制转换
  1. bin()十进制转换二进制
  2. oct()十进制转换八进制
  3. hex()十进制转换十六进制
  4. int(数据,base=进制)转换十进制
print(bin(56))
print(oct(56))
print(hex(56))
print(int('0b111000', base=2))
print(int('0o70', base=8))
print(int('0x38', base=16))
  • 编码相关
  1. chr()将十进制数字转换成unicode编码中的对应字符
  2. ord()根据字符在Unicode编码中找到对应的数字编号
  • 应用(随机验证码)
import random


def get_random_code(length=6):
    data = []
    for i in range(length):
        data.append(chr(random.randint(65, 90)))
    return ''.join(data)


v = get_random_code()
print(v)
  • 高级内置函数
  1. filter()对序列进行筛选,获取符合条件的序列
  2. map()遍历序列,对序列中的每个元素进行操作,生成新的序列
  3. educe()对序列中的元素进行累计操作
案例(map)

* 第一个参数必须是函数,函数参数一个
* 第二个参数必须是可迭代的(可以for循环)
v1 = [11, 22, 33]
result = map (lambda x:x+100,v1)
print(result)   # py2.x输出[111,122,133] py3.x输出可迭代对象,可以进行list()强制换案例(filter)
案例(filter)

第一个参数必须是函数,函数参数一个

第二个参数必须是可迭代的(可以for循环)

v1 = [11, 22, 'hhh',33]
result = filter (lambda x: type(x)==int,v1)
# result = filter (lambda x:True if type(x)==int else False,v1) #第二种写法
print(result)   # py2.x输出[11,22,33] py3.x输出可迭代对象,可以进行list()强制换案例(filtr)
案例(reduce)

py3.x使用reduce需要先导入模块functools

第一个参数必须是函数,函数参数必须是两个

第二个参数必须是可迭代的(可以for循环)

import functools

v1 = [1, 2, 3, 4]
result = functools.reduce(lambda x, y: x + y, v1)   # 加减乘除都可
print(result)   # 输出结果:10
  • 其他
  1. id()查看内存地址
s1 = 123
print(id(s))    # 输出结果类似于:2414242616752
  1. type()查看数据类型

s1 = 123
print(type(s))  # 输出结果:<class 'int'>
s2 = '123'
print(type(s))  # 输出结果:<class 'str'>
  1. len()计算对象长度

s1 = [1, 2, 3, 4]
print(len(s1))  # 输出结果:4
s2 = 'alexsb'
print(len(s2))  # 输出结果:6
  1. open()打开文件

with open('a.txt', mode='w', encoding='utf-8') as f2:
    pass
f1 = open('a.txt', mode='w', encoding='utf-8')
f1.close()
  1. range()创建数字序列

l1 = [i for i in range(10)]
print(l1)   # 输出结果:[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
  1. reversed()反转一个可迭代对象,返回一个迭代器

s1 = 'alex'
print(reversed(s1)) # <reversed object at 0x0000028B33E98390>
s2 = [1, 2]
print(reversed(s2)) # <list_reverseiterator object at 0x0000028B33E98390>
  1. sorted()排序,形成新数据集合

语法:sorted(iterable,key=None,reverse=False)

iterable : 可迭代对象

key: 排序规则(排序函数),在sorted内部会将可迭代对象中的每一个元素传递给这个函数的参数.根据函数运算的结果进行排序

reverse :是否是倒叙,True 倒叙 False 正序

lst = [1,3,2,5,4]
lst2 = sorted(lst)
print(lst)    #原列表不会改变
print(lst2)   #返回的新列表是经过排序的
 
 
lst3 = sorted(lst,reverse=True)
print(lst3)   #倒叙
 
结果:
[1, 3, 2, 5, 4]
[1, 2, 3, 4, 5]
[5, 4, 3, 2, 1]

字典使用sorted排序

dic = {1:'a',3:'c',2:'b'}
print(sorted(dic))   # 字典排序返回的就是排序后的key
 
结果:
[1,2,3]



和函数组合使用

# 定义一个列表,然后根据一元素的长度排序
lst = ['天龙八部','西游记','红楼梦','三国演义']
 
# 计算字符串的长度
def func(s):
    return len(s)
print(sorted(lst,key=func))
 
# 结果:
# ['西游记', '红楼梦', '天龙八部', '三国演义']


和lambda组合使用

lst = ['天龙八部','西游记','红楼梦','三国演义']
 
print(sorted(lst,key=lambda s:len(s)))
 
结果:
['西游记', '红楼梦', '天龙八部', '三国演义']
 
 
lst = [{'id':1,'name':'alex','age':18},
    {'id':2,'name':'wusir','age':17},
    {'id':3,'name':'taibai','age':16},]
 
# 按照年龄对学生信息进行排序
 
print(sorted(lst,key=lambda e:e['age']))
 
结果:
[{'id': 3, 'name': 'taibai', 'age': 16}, {'id': 2, 'name': 'wusir', 'age': 17}, {'id': 1, 'name': 'alex', 'age': 18}]
  1. zip() 拉链方法,函数用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元祖组成的内容,如果各个迭代器的元素个数不一致,则按照长度最短的返回

lst1 = [1,2,3]
lst2 = ['a','b','c','d']
lst3 = (11,12,13,14,15)
for i in zip(lst1,lst2,lst3):
    print(i)
结果:
(1, 'a', 11)
(2, 'b', 12)
(3, 'c', 13)
  1. hash()获取一个对象的哈希值(int、str、bool、tuple)

print(hash(123))
print(hash('123'))
print(hash('asfr'))
print(hash(True))
print(hash(False))
print(hash((1, 2, 3)))
"""
输出结果:
123
4582654100250779780
3968706218629953014
1
0
2528502973977326415
"""
  1. dir()查看数据类型功能方法

print(dir(list))
print(dir(str))
print(dir(float))
print(dir(set))
  1. bytes() 用于不同编码之间的转换

s = '你好'
bs = s.encode('utf-8')
print(bs)
s1 = bs.decode('utf-8')
print(s1)
bs = bytes(s, encoding='utf-8')
print(bs)
b = '你好'.encode('gbk')
b1 = b.decode('gbk')
print(b1.encode('utf-8'))
"""
输出结果:
b'\xe4\xbd\xa0\xe5\xa5\xbd'
你好
b'\xe4\xbd\xa0\xe5\xa5\xbd'
b'\xe4\xbd\xa0\xe5\xa5\xbd'
"""
  1. enumerate()枚举

    enumerate在字典上是枚举、列举的意思enumerate参数为可遍历/可迭代的对象(如列表、字符串)enumerate多用于在for循环中得到计数,利用它可以同时获得索引和值,即需要index和value值的时候可以使用enumerateenumerate()返回的是一个enumerate对象


    >>> lst = [1,2,3,4,5,6]
    >>> for index,value in enumerate(lst):
      print ('%s,%s' % (index,value))
      
    0,1
    1,2
    2,3
    3,4
    4,5
    5,6
    #指定索引从1开始
    >>> lst = [1,2,3,4,5,6]
    >>> for index,value in enumerate(lst,1):
    print ('%s,%s' % (index,value))
    
    1,1
    2,2
    3,3
    4,4
    5,5
    6,6
    
    #指定索引从3开始
    >>> for index,value in enumerate(lst,3):
    print ('%s,%s' % (index,value))
    
    3,1
    4,2
    5,3
    6,4
    7,5
    8,6


  2. iter()转换为迭代器

  3. next()迭代器取值

s = '12345678'
obj = iter(s)
print(next(obj))
print(next(obj))
print(next(obj))
print(next(obj))
..........              # 取后续值
  1. globals()以字典的形式返回全局作用域所有的变量对应关系。

  2. locals()以字典的形式返回当前作用域的变量的对应关系。

# 在全局作用域下打印,则他们获取的都是全局作用域的所有的内容。
a = 2
b = 3
print(globals())
print(locals())
'''
{'__name__': '__main__', '__doc__': None, '__package__': None,
'__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x000001806E50C0B8>, 
'__spec__': None, '__annotations__': {},
'__builtins__': <module 'builtins' (built-in)>, 
'__file__': 'D:/lnh.python/py project/teaching_show/day09~day15/function.py',
'__cached__': None, 'a': 2, 'b': 3}
'''

# 在局部作用域中打印。
a = 2
b = 3
def foo():
    c = 3
    print(globals()) # 和上面一样,还是全局作用域的内容
    print(locals()) # {'c': 3}
foo()
  1. help() 查看函数或模块的具体使用方法(以列表append方位为例)

print(help(list.append))
"""
输出结果:
append(self, object, /)
    Append object to the end of the list.

None
"""
  1. callable()判断变量是否可调用

name = 'alex'
def func():
    pass
print(callable(name))  # 输出结果:False
print(callable(func))  # 输出结果:True
  1. repr()原形毕露 全部显示尤其''

# %r  原封不动的写出来
# name = 'william'
# print('我叫%r'%name)    # 我叫'william'

# repr 原形毕露
print(repr('{"name":"alex"}'))
print('{"name":"alex"}')
"""
输出结果:
'{"name":"alex"}'
{"name":"alex"}
"""
  1. all()判断可迭代对象中全部元素是否全是真

  2. any()判断可迭代对象中是否有元素为真

print(all([1, 2, True, 0])) # False
print(any([1, '', 0]))  # True
  • 慎用
  1. eval() 剥去字符串外衣,返回里面的本质
s1 = '1+2'
print(s1)   # 1+2
print(eval(s1)) # 3
s2 = "{'name':'alex'}"
print(type(s2)) # <class 'str'>
print(type(eval(s2)))   # <class 'dict'>
  1. exec() 代码流,过程,无返回值

s3 = """
for i in range(3):
    print(i)
"""
exec(s3)    # 0 1 2

4.匿名函数

匿名函数,顾名思义就是没有名字的函数,那么什么函数没有名字呢?这个就是我们以后面试或者工作中经常用匿名函数 lambda,也叫一句话函数。

现在有一个需求:你们写一个函数,此函数接收两个int参数,返回和值。

def func(a,b):
    return a+b
print(func(3,4))

那么接下来我们用匿名函数完成上面的需求:

func = lambda a,b: a+b
print(func(3, 4))  # 7

我们分析一下上面的代码:

语法:

  函数名 = lambda 参数:返回值

    1)此函数不是没有名字,他是有名字的,他的名字就是你给其设置的变量,比如func.

    2)lambda 是定义匿名函数的关键字,相当于函数的def.

    3)lambda 后面直接加形参,形参加多少都可以,只要用逗号隔开就行。

func = lambda a,b,*args,sex= 'alex',c,**kwargs: kwargs
print(func(3, 4,c=666,name='alex'))  # {'name': 'alex'}
# 所有类型的形参都可以加,但是一般使用匿名函数只是加位置参数,其他的用不到。

    4)返回值在冒号之后设置,返回值和正常的函数一样,可以是任意数据类型。

    5)匿名函数不管多复杂.只能写一行.且逻辑结束后直接返回数据

接下来做几个匿名函数的小题:

写匿名函数:接收一个可切片的数据,返回索引为0与2的对应的元素(元组形式)。

func = lambda x:(x[0],x[2])
print(func('afafasd'))
func = lambda x:(x[0],x[2])
print(func('afafasd'))

写匿名函数:接收两个int参数,将较大的数据返回。

func = lambda x,y: x if x > y else y
print(func(3,100))
func = lambda x,y: x if x > y else y
print(func(3,100))