1. 程式人生 > >day05_雷神_函數進階

day05_雷神_函數進階

python 相加 源碼 結果 amp args %s mat spec

#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=‘\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.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_雷神_函數進階