day05_雷神_函数进阶

Posted houbinglei

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了day05_雷神_函数进阶相关的知识,希望对你有一定的参考价值。

#day05

1、迭代器

1.1可迭代对象

str,list,tuple,dict,set,range,文件句柄 等都是可迭代对象

第一种方法:在该对象中,含有__iter__方法的就是可迭代对象,遵循可迭代协议。

print(dir(str)) 
dir() 打印出str对象的所有方法。

print(‘__iter__‘ in dir(list))
返回值: True 说明是可迭代对象

第二种方法: isinstance("123",Iterable)

from collections import Iterable  (需要import Iterable)
a = isinstance("[1,2,3]", Iterable)
print(a)

1.2迭代器

内部含有__iter__ 且含有__next__方法的对象就是迭代器,遵循迭代器协议。

将可迭代对象转换为迭代器(两种方法)

s1 = "abc"
obj_s1 = iter(s1)  #方法一
obj_s1 = s1.__iter__()  #方法二
print(obj_s1)
结果:<str_iterator object at 0x000002370C657390>

迭代器只能通过__next__方法来读取值:
print(obj_s1.__next__())  # a
print(obj_s1.__next__())  # b
print(obj_s1.__next__())  # c
print(obj_s1.__next__())  # 报错:StopIteration

判断是否是迭代器的方法一:

s1 = "asd"
print(‘__iter__‘ in dir(s1))  #True
print(‘__next__‘ in dir(s1))  #False

obj_s1 = iter(s1)
print(‘__iter__‘ in dir(obj_s1))  #True
print(‘__next__‘ in dir(obj_s1))  #True

方法二:

s1 = "asd"
obj_s1 = iter(s1)
print(isinstance(s1,Iterator))    #False
print(isinstance(obj_s1,Iterator))    #True

迭代器的好处

节省内存
惰性机制
单向不可逆

1.3生成器

生成器的本质就是迭代器,他是自定义的迭代器(用Python写的)。

  1. 函数的方式构建一个生成器:
示例1:
def func1():
    print(111)
    yield 222
    print(333)
    print(444)
obj_1 = func1()   # g_obj = func1()  # 生成器对象
#  凡是函数中见到yield 他就是生成器
print(obj_1)

print(obj_1.__next__())   # 111, 222  一个next对应一个yield,一一对应
print(obj_1.__next__())   # 报错StopIteration 

示例2:
def cloth():
for i in range(1,5001):
    yield ‘衣服%s‘ %i
g_obj = cloth()  #生成器对象
print(g_obj)    #<generator object cloth at 0x0000020ADFBCDE08>
for i in range(1,51):
    print(g_obj.__next__())  # 先来50套
for i in range(1,101):
    print(g_obj.__next__())  # 再加100套,从50到了150套,因为迭代器单向不可逆

send

send和next都是对生成器取值,每一个都要对应一个yield,send 会给上一个yield 发送一个值。

send 不能用在第一次取值。最后一个yield 不能得到值

def func1():
    count = yield 666
    print(count)
    yield 777
    yield 888
g_obj = func1()
print(g_obj.__next__())
# print(g_obj.__next__())
# 666
# None
# 777
print(g_obj.send(‘taibai‘))  
# 666
# taibai
# 777
# print(g_obj.send(‘alex‘))  # 相当于给yield 777 整体赋值为"alex",只是没有打印

2、列表推导式(生成器表达式)

遍历模式 l = [ i for i in range(1,11)]

[ (结果需要的变量形式)变量 for 变量 in iterable ]

[变量(加工后的变量) for 变量 in iterable] 遍历模式

l2 = [‘python%s期‘ % i for i in range(1,23)]
print(l2)

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

l2 = [i for i in range(1,31) if i % 3 == 0]
print(l2)
l2_obj = (i for i in range(1,31) if i % 3 == 0)  #将[]换成()就是生成器表达式了。
print(l2_obj)
print(l2_obj.__next__())
print(l2_obj.__next__()) 

li = ["a","c",‘houbinglei‘,‘alex‘]
l = [i.upper() for i in li if len(i)>=3 ]
print(l)

区别

# 列表推导式:简单,一行搞定。
# 特别复杂的数据列表推导式无法实现,只能用其他方式实现。
# 列表推导式不能排错。
# 列表推导式与生成器表达式区别
# 1 ,列推直观能看出,但是占内存
# 2,生成器表达式不易看出,但是节省内存。

示例:-
x = {
    ‘name‘:‘alex‘,
    ‘Values‘:[{‘timestamp‘:1517991992.94,
         ‘values‘:100,},
        {‘timestamp‘: 1517992000.94,
        ‘values‘: 200,},
        {‘timestamp‘: 1517992014.94,
         ‘values‘: 300,},
        {‘timestamp‘: 1517992744.94,
         ‘values‘: 350},
        {‘timestamp‘: 1517992800.94,
         ‘values‘: 280}
        ],}

li = [[i[‘timestamp‘],i[‘values‘]] for i in x[‘Values‘] ]
print(li)
关键:从要的数据类型分析出规律。

字典推导式

将一个字典的key和value对调
mcase = {‘a‘: 10, ‘b‘: 34}
mcase_frequency = {mcase[k]: k for k in mcase}
print(mcase_frequency)

3、 内置函数

见过的

‘‘‘
len()
print()
input()
range()
list()  
tuple()
str()
int()
set()。。。。。
‘‘‘

dict()

field = ["id","name","age","phone","job"]
def yie_file():
    with open("yuan_gong",encoding="utf-8") as f:
        for line in f:
            yield line.strip().split()
li = []
for i in yie_file():
    dic = dict(zip(field,i))
    if int(dic[‘age‘]) > 25:
        print(dic)
    else:
        li.append(dic)
print(li)
结果:
{‘id‘: ‘4‘, ‘name‘: ‘houbinglei‘, ‘age‘: ‘27‘, ‘phone‘: ‘17718351482‘, ‘job‘: ‘IT‘}
[{‘id‘: ‘2‘, ‘name‘: ‘Egon‘, ‘age‘: ‘23‘, ‘phone‘: ‘13304320533‘, ‘job‘: ‘Tearcher‘}, {‘id‘: ‘3‘, ‘name‘: ‘nezha‘, ‘age‘: ‘25‘, ‘phone‘: ‘1333235322‘, ‘job‘: ‘IT‘}]

1.1. 作用域相关

locals :函数会以字典的类型返回当前位置的全部局部变量。

globals:函数以字典的类型返回全部全局变量。

1.2 其他相关
1.2.1 字符串类型代码的执行,eval,exec

    eval:去除字符串两边的引号,输出里边的结果,并返回最终结果。执行字符串表达式。
print(eval(‘1 + 2 +3‘))
print(eval("{‘name‘:‘alex‘}"),type(eval("{‘name‘:‘alex‘}")))

  exec:也是去除两边的引号,但是不返回结果,执行代码,执行文件。
s1 = ‘‘‘
for i in range(5):
    print(i)
‘‘‘
print(exec(s1))

1.2.2 输入输出相关

‘‘‘ 源码分析
def print(self, *args, sep=‘ ‘, end=‘
‘, file=None): # known special case of print
    """
    print(value, ..., sep=‘ ‘, end=‘
‘, 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.2.3 内存相关

hash:获取一个对象(可哈希对象:int,str,Bool,tuple)的哈希值。

id:用于获取对象的内存地址。

print(hash(‘arg‘))
print(id(‘abc‘))  # 2033192957072

1.2.3文件操作相关

  open:函数用于打开一个文件,创建一个 file 对象,相关的方法才可以调用它进行读写。

1.2.4模块相关__import__ 

  import:函数用于动态加载类和函数 。

1.2.5帮助

  help:函数用于查看函数或模块用途的详细说明。

1.2.6 调用相关

callable:函数用于检查一个对象是否是可调用的。如果返回True,object仍然可能调用失败;但如果返回False,调用对象ojbect绝对不会成功。

name = ‘alex‘

def func1():
    print(111)
print(callable(name))  False
print(callable(func1))  True
函数名加括号就能用,再面向对象比较有用。

1.2.7查看内置属性

dir:函数不带参数时,返回当前范围内的变量、方法和定义的类型列表;带参数时,返回参数的属性、方法列表。

dir()   #  获得当前模块的属性列表

1.3 迭代器生成器相关

# 首先获得Iterator对象:
it = iter([1, 2, 3, 4, 5])
# 循环:
while True:
    try:
        # 获得下一个值:
        x = next(it)
        print(x)
    except StopIteration:
        # 遇到StopIteration就退出循环
        break

iter:函数用来生成迭代器(讲一个可迭代对象,生成迭代器)。
from collections import Iterable
from collections import Iterator
l = [1,2,3]
print(isinstance(l,Iterable))  # True
print(isinstance(l,Iterator))  # False

l1 = iter(l)
print(isinstance(l1,Iterable))  # True
print(isinstance(l1,Iterator))  # True

1.4 基础数据类型相关

1.4.1数字相关(14)

数据类型(4):

    bool :用于将给定参数转换为布尔类型,如果没有参数,返回 False。

    int:函数用于将一个字符串或数字转换为整型。

    float:函数用于将整数和字符串转换成浮点数。

进制转换(3):

    bin:将十进制转换成二进制并返回。

    oct:将十进制转化成八进制字符串并返回。

    hex:将十进制转化成十六进制字符串并返回。

数学运算(7):

abs:函数返回数字的绝对值。

print(abs(-5))  # 5

divmod:计算除数与被除数的结果,返回一个包含商和余数的元组(a // b, a % b)。

print(divmod(7,2))  # (3, 1)

round:保留浮点数的小数位数,默认保留整数。

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

pow:求xy次幂。(三个参数为xy的结果对z取余)

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

sum:对可迭代对象进行求和计算(可设置初始值)。

l1 = [i for i in range(100)]
print(sum(l1))
print(sum(l1,100)) # 初始值是100 ,最后算完再加上100

min:返回可迭代对象的最小值(可加key,key为函数名,通过函数的规则,返回最小值)。

print(min([1,2,3]))  # 返回此序列最小值

ret = min([1,2,-5,],key=abs)  # 按照绝对值的大小,返回此序列最小值
print(ret)

dic = {‘a‘:3,‘b‘:2,‘c‘:1}
print(min(dic,key=lambda x:dic[x]))

###这里可迭代对象如果是字典,x默认是每个字典的key值;
###如果可迭代对象是s = [[3,2],[7,4],[1,6]]这种,x会默认接收每个元素的第一个值。

max:返回可迭代对象的最大值(可加key,key为函数名,通过函数的规则,返回最大值)

dic = {‘a‘:3,‘b‘:2,‘c‘:1}
print(max(dic,key=lambda x:dic[x]))
# x为dic的key,lambda的返回值(即dic的值进行比较)返回最大的值对应的键,x默认接收字典的key。

1.4.2和数据结构相关(24)

列表和元祖(2)

    list:将一个可迭代对象转化成列表(如果是字典,默认将key作为列表的元素)。

    tuple:将一个可迭代对象转化成元祖(如果是字典,默认将key作为元祖的元素)。

l = list((1,2,3))
print(l)

l = list({1,2,3})
print(l)

l = list({‘k1‘:1,‘k2‘:2})
print(l)

相关内置函数(2)

    reversed:将一个序列翻转,并返回此翻转序列的迭代器。

l3 = [2, 3, 9, 8, 7, 4]
l3.reverse()
print(l3)
l_obj = reversed(l3)
print(l_obj)   #<list_reverseiterator object at 0x0000025DDEB47908>
for i in l_obj:
    print(i)
print(sum(l_obj))  # 33  sum直接求和迭代器。
print(sum(l3))      # 33  sum 本身就可以求和可迭代对象。

    slice:构造一个切片对象,用于列表的切片。

字符串相关(9)

    str:将数据转化成字符串。

    format:与具体数据相关,用于计算各种小数,精算等。

print(format(‘test‘, ‘<30‘))    左对齐
print(format(‘test‘, ‘>20‘))    右对齐
print(format(‘test‘, ‘^20‘))    剧中

bytes:用于不同编码之间的转化。相当于encode

s1 = "abc"
print(bytes(s1,encoding="utf-8"))  
print(s1.encode("utf-8"))

两种方法将str转换为bytes数据类型;解码只能用decode

ord:输入字符找该字符编码的位置   unicode

print(ord(‘a‘))  # 97
print(ord(‘中‘))   #20013

chr:输入位置数字找出其对应的字符

print(chr(97))
print(chr(20013))

ascii:是ascii码中的返回该值,不是就返回/u...

print(ascii(‘a‘))
print(ascii(‘中‘))

repr:返回一个对象的string形式(原形毕露)。

print(repr(‘{"name":"alex"}‘),type(repr(‘{"name":"alex"}‘)))  #‘{"name":"alex"}‘ <class ‘str‘>
print(‘{"name":"alex"}‘)  
print(‘python%s期‘ % ‘22‘)  # python22期
print(‘python%r期‘ % ‘22‘)   # python‘22‘期

数据集合(3)

dict:创建一个字典。

set:创建一个集合。

frozenset:返回一个冻结的集合,冻结后集合不能再添加或删除任何元素。

***  sorted:对所有可迭代的对象进行排序操作。返回列表。

L = [(‘a‘, 1), (‘c‘, 3), (‘d‘, 4),(‘b‘, 2), ]
sorted(L, key=lambda x:x[1])               # 利用key
[(‘a‘, 1), (‘b‘, 2), (‘c‘, 3), (‘d‘, 4)]

x:自动获取可迭代对象的每一个值,并默认按照每个元素的第一个值排序。
字典默认是对Key排序。
dic = {"c":1,"a":3,"b":9}
print(sorted(dic))   #[‘a‘, ‘b‘, ‘c‘]
 
 
students = [(‘john‘, ‘A‘, 15), (‘jane‘, ‘B‘, 12), (‘dave‘, ‘B‘, 10)]
sorted(students, key=lambda s: s[2])            # 按年龄排序
[(‘dave‘, ‘B‘, 10), (‘jane‘, ‘B‘, 12), (‘john‘, ‘A‘, 15)]
 
sorted(students, key=lambda s: s[2], reverse=True)    # 按降序
[(‘john‘, ‘A‘, 15), (‘jane‘, ‘B‘, 12), (‘dave‘, ‘B‘, 10)]

*** enumerate:枚举,返回一个枚举对象。

dic = {"c":1,"a":3,"b":9}
for i in enumerate(dic):
    print(i)
结果:
(0, ‘c‘)
(1, ‘a‘)
(2, ‘b‘)

for index,key in enumerate(dic):
    print("序号{}的值是{}".format(index,key))
结果:
序号0的值是c
序号1的值是a
序号2的值是b

all:可迭代对象中,全都是True才是True

any:可迭代对象中,有一个True 就是True

l1 = [1, ‘alex‘, 3]
l2 = [0, ‘‘, False,(), 1]
print(all(l1))
print(any(l2))

***zip 拉链方法,函数用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,并没有返回列表,需要用for循环读取这个迭代器。

l1 = [1,2,3,]
l2 = [‘a‘,‘b‘,‘c‘,5]
l3 = (‘*‘,‘**‘,(1,2,3),666,777)
for i in zip(l1, l2, l3):
    print(i)

结果:
(1, ‘a‘, ‘*‘)
(2, ‘b‘, ‘**‘)
(3, ‘c‘, (1, 2, 3))

***map:会根据提供的函数对指定序列做映射。返回的是迭代器,类似于列表推导式的遍历模式。

>>>def square(x) :            # 计算平方数
...     return x ** 2
... 
>>> map(square, [1,2,3,4,5])   # 计算列表各个元素的平方
[1, 4, 9, 16, 25]
<map object at 0x00000268A1747908>
>>> map(lambda x: x ** 2, [1, 2, 3, 4, 5])  # 使用 lambda 匿名函数
[1, 4, 9, 16, 25]
 
# 提供了两个列表,对相同位置的列表数据进行相加
>>> map(lambda x, y: x + y, [1, 3, 5, 7, 9], [2, 4, 6, 8, 10])
[3, 7, 11, 15, 19]

 filter:过滤·。

类似于[i for i in range(1,8) if i % 2 == 0 ]
def func(x):return x%2 == 0
ret = filter(func,[1,2,3,4,5,6,7])
print(ret)   #<filter object at 0x0000018EE48679B0>
for i in ret:
    print(i)

    portfolio = [
{‘name‘: ‘IBM‘, ‘shares‘: 100, ‘price‘: 91.1},
{‘name‘: ‘AAPL‘, ‘shares‘: 50, ‘price‘: 543.22},
{‘name‘: ‘FB‘, ‘shares‘: 200, ‘price‘: 21.09},
{‘name‘: ‘HPQ‘, ‘shares‘: 35, ‘price‘: 31.75},
{‘name‘: ‘YHOO‘, ‘shares‘: 45, ‘price‘: 16.35},
{‘name‘: ‘ACME‘, ‘shares‘: 75, ‘price‘: 115.65}]

ret = filter(lambda x:x[‘price‘] > 100, portfolio )
print(ret)  # <filter object at 0x0000021B7F357E48>
for i in ret:
    print(i)

min,max,sorted,map,filter

返回结果:

filter: ret = filter(lambda x:x[‘price‘] > 100, portfolio )
            print(ret)
            <filter object at 0x0000021B7F357E48>  返回迭代器

sorted: students = [(‘john‘, ‘A‘, 15), (‘jane‘, ‘B‘, 12), (‘dave‘, ‘B‘, 10)]
            sorted(students, key=lambda s: s[2])            # 按年龄排序
            [(‘dave‘, ‘B‘, 10), (‘jane‘, ‘B‘, 12), (‘john‘, ‘A‘, 15)]  返回列表

zip: ret = zip(l_new,l2,tu)
            print(ret) <zip object at 0x00000292D35BE5C8> 返回迭代器
        for i in a:
            print(i) 
            (3, ‘oldboy‘, ‘**‘)   返回元祖

map:  ret = map(lambda x:x[‘shares‘] * x[‘price‘], portfolio)  # 字典的两个值相乘。
        print(ret)  <map object at 0x000002CFC04E7EB8>  返回迭代器
        li = []
        for i in ret:
            li.append(i)
        print(li)

list: l=[{‘name‘:‘alex‘},{‘name‘:‘y‘}]
        ret = map(lambda x:x[‘name‘]+‘SB‘, l)  ret是迭代器。
        print(list(ret))    list()将可迭代对象转换为列表,同样可以直接转换迭代器。
        结果: [‘alexSB‘, ‘ySB‘]

4 匿名函数

def func(x,y): return x + y
    print(func(3,4))
func1 = lambda x,y: x + y
    print(func1(3,4))
#def func1(x): return x**2
res = map(lambda x: x**2,[1,5,7,4,8])
for i in res:
    print(i)

5.函数的有用信息

from functools import wraps

def logger(f):
    @wraps(f)
    def inner(*args, **kwargs):
        """
        :param args: 函数名,密码
        :param kwargs: 备用
        :return:  True
        """
        ret = f(*args, **kwargs)
        return ret
    return inner

@logger
def login(username,password):
    """
    此函数是完成登录功能的函数,需要用户名,和密码两个参数,返回True 登陆成功
    :return:  True
    """
    print(666)
    return True
login(1,2)  #inner()
# # login(‘alex‘, 123)
print(login.__doc__)
print(login.__name__)

遇到装饰器的时候,要还是打印原函数的有用信息,需要from functools import wraps。并且正在inner函数上添加@wraps(f)。

6. 装饰器的升级

带参数的装饰器

1,将@ 与函数分开@ timmerout(flag) 返回了timmer

2,将@timmer结合

def timmerout(flag1):  # flag1 =flag
    def timmer(f):
        def inner(*args,**kwargs):
            if flag1:
                print(flag1)
                start_time = time.time()
                ret = f(*args,**kwargs)
                end_time = time.time()
                print(‘此函数的执行效率%s‘ % (end_time - start_time))
                return ret
            else:
                ret = f(*args, **kwargs)
                return ret
        return inner
    return timmer

@timmerout(‘京东‘)  # 1,将@ 与函数分开@     timmerout(flag)  返回了timmer 2,将@timmer结合。
def JDshop():
    time.sleep(0.3)
    print(‘非常复杂......‘)
    return 666

@timmerout(‘京东‘)
def JD():
    time.sleep(0.3)
    print(‘非常复杂......‘)
    return 666


@timmerout(‘淘宝‘)
def taobao():
    time.sleep(0.1)
    print(‘非常复杂......‘)
    return 666

@timmerout(‘淘宝‘)
def taobaoshop():
    time.sleep(0.1)
    print(‘非常复杂......‘)
    return 666

taobaoshop()
结果 :
淘宝
非常复杂......
此函数的执行效率0.10024571418762207

多个装饰器装饰一个函数

@wrapper2  # f = warpper2(f)  里面的f是inner1 外面的f是inner2
@wrapper1  # f = warpper1(f)  里面的f函数名 外面的f 是inner1
def f():
    print(‘in f‘)  # 3

f()  # inner2()

wrapper2 ,before func
wrapper1 ,before func
in f
wrapper1 ,after func
wrapper2 ,after func

以上是关于day05_雷神_函数进阶的主要内容,如果未能解决你的问题,请参考以下文章

day04_雷神_函数

day06_雷神_面向对象初识

pyrhon学习_day11___函数进阶

day07面向对象进阶

day07-01-面向对象进阶

day14 生成器的进阶