1. 程式人生 > >python 3.5學習筆記(第四章)

python 3.5學習筆記(第四章)

ping 函數返回值 使用 family __next__ 什麽 san 直接 all

本章內容:

  一、、裝飾器

  二、生成器

  三、叠代器

  四、python中的內置方法

  五、json & pickle 的數據序列化及反序列化

  六、程序目錄結構規範

  七、補充內容

一、裝飾器:

  1、概念:裝飾器的本質是函數,用於裝飾其他函數,就是給其他函數添加附加的功能

  2、什麽情況下要使用裝飾器?

    (1)不能修改被裝飾函數的源代碼

    (2)不能修改被裝飾函數的調用方式

    (裝飾器對於被裝飾函數是完全透明的,不會影響被裝飾函數)

  示例:

  定義一個sayhi()函數,調用函數時,打印“你好,xx”,代碼如下:

def sayhi(name):
    
print(Hi,,name) sayhi("MR")

  現在想要給這個函數添加新功能,計算該程序執行的時間,要求不能對原函數進行修改,而且不能修改原函數的調用方式。

import time
def timer(func): def wrapper(*args, **kwargs): first_time = time.time() time.sleep(2) second_time = time.time() print(the function run %s % (second_time - first_time))
return func(*args, **kwargs) return wrapper @timer # 相當於執行了 sayhi = timer(sayhi) def sayhi(name): print(Hi,,name) sayhi("MR")
  調用sayhi函數,不僅會運行sayhi函數本身,還會在sayhi函數前運行timer函數。timer()是一個裝飾器,返
回一個函數,所以原來的sayhi函數 任然存在,只是現在同名的sayhi變量指向了新的函數,於是調用sayhi將執行
新的函數,即在timer函數中返回wrapper函數。
  wrapper函數的參數定義是(*args, **kwargs),所以wrapper函數可以接受任意參數的調用。在wrapper
函數
內部進行sleep操作,並打印休眠時間,再緊接著調用原始sayhi函數。

二、生成器

1、列表生成式:

(1)普通方法生成一個列表

a= []
for i in range(10):
    a.append(i * 2)
print(a)
>>>[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]

(2)利用列表生成式生成一個相同的列表

list1= [ i * 2 for i in range(10)]
print(list1)
>>>[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]

2、字典生成式:把列表生成式中的 [ ] 換成 { } 就是字典生成式

b = {i:i%2==0 for i in range(10)}
print(b)

3、通用生成器

  生成器是一個包含yield關鍵字的函數,當它被調用的時候,在函數體中的代碼不會被執行,而回返回一個叠代器。每次請求一個值就會執行生成器中的代碼,直到遇到一個yield或者return語句。yield語句意味著應該生成一個值,return語句意味著生成器要停止執行(不再生成任何東西,return語句只有在一個生成器中使用的時候才會進行無參數調用)。

  換句話說,生成器是由兩個部分組成的:生成器的函數和生成器的叠代器。生成器的函數使用def語句定義的,包含yield部分,生成器的叠代器是這個函數的返回部分,這兩個實體合在一起叫做生成器。

  生成器推導式:把列表生成式中的 [ ] 換成 () 就是生成器推導式

示例:

a = ( i * 2 for i in range(10))
for x in a:
print(x)

   註意:

  (1)生成器不能直接打印出來,因為只有在循環到某一個數據的時候,這個數據才會在內存中實際出現

  (2)生成器不是列表,不能切片,只有在調用的時候才會生成相應的數據

  (3)生成器只能記住當前位置的內容,上一個內容在調用之後就被刪除了

  (4)生成器可以用作 for 循環,還可以被next方法( __next__() )不斷調用,並返回下一個值,直到最後拋出StopIteration 錯誤表示無法繼續返回下一個值。(對於異常可以使用 try-except語句來解決)

  ‘‘‘

  yield 的作用:保存當前狀態並返回,然後再次調用的時候,會回到yield

  send 的作用:調用yield ,同時給yield 傳值

  next 的作用:只會調用yield ,但是不會給yield 傳值

  ‘‘‘

   函數生成器示例:

def myGen():
    print(生成器被執行!)
    yield 1 # 打印1
    yield 2 # 打印2
myG = myGen() print(next(myG)) print(next(myG))
# 第一次調用生成器,會打印‘生成器被執行!‘,然後在yield前停下 ,每使用一次next方法都會執行一次yield。

4、斐波那契數列

(1)普通方法

list_fib = []
def fib(max):
    a = 0
    b = 1
    n = 0
    while n < max:
        print(b)
        list_fib.append(b)
        a,b = b, a + b  # 這裏是給 a 和 b 同時賦值
        n = n+1

fib(10)
print(list_fib = ,list_fib)

(2)用函數生成器實現

def fib(max):
    a = 0
    b = 1
    n = 0
    while n < max:
        yield  b
        a,b = b, a + b  # 同時賦值
        n = n+1

f = fib(10)
for i in range(10):
    print(f.__next__())
# 如果調用next的次數超過範圍,則會拋出異常

三、叠代器

1、概念:

  叠代的意思是重復做一件事很多次,類似循環。只要某一個對象實現了__iter__() 方法就可以叠代。__iter__() 方法會返回一個叠代器(iterator),所謂的叠代器就是具有next方法的對象。在調用next 的方法的時候,叠代器會返回它的下一個值。如果next方法被調用了,但是並沒有值可以返回,就會拋出StopIteration異常。

2、為什麽要使用叠代器?

  如果有一個函數,可以一個接一個的計算值,那麽在使用時可能是計算一個值時獲取一個值——而不是通過列表等數據類型一次獲取所有值。如果有很多的值,就會占用太多的內存,叠代器可以避免這種情況。

3、為什麽列表、字典、字符串不是叠代器?

  因為python 的Iterator 對象表示的是一個數據流,Iterator 對象可以被next() 函數調用並不斷返回下一個數據,知道沒有數據時拋出 StopIteration 錯誤,可以把這個數據流看作是一個有序序列,但是我們並不能提前知道序列的長度,只有在需要反回下一個數據的時候它才會計算。叠代器甚至可以表示一個無限大的數據流,比如全體自然數,而列表等數據類型是不可能存儲全體自然數的。

4、把可叠代對象轉化為叠代器的方法:

  iter() 或 __iter__()

a = [1,2,3]
c = iter(a)
print(isinstance(c,Iterator))  # isinstance()用於判斷是否為叠代器或者可叠代對象
# .__iter__()
print(isinstance([].__iter__(),Iterator))

5、總結:

  (1)可以直接用於for 循環的對象稱為可叠代對象(Iterable),可以被next() 方法不斷調用並返回下一個值的對象是叠代器(Iterator),叠代器表示一個惰性計算的序列。叠代器一定是可叠代對象,但是可叠代對象不一定是叠代器。

  (2)isinstance() 用於判斷是否可為叠代對象或者叠代器

print(isinstance([],Iterable))

>>>True

a = [1,2,3] print(isinstance(a,Iterator))
>>>False

  (3)生成器一定是叠代器,但是叠代器不一定是生成器。

b = ( x*2 for x in range(5))
print(isinstance(b,Iterator))
>>>True

  (4)list 、 dict 、str 是可叠代對象,但是不是叠代器,但是可以轉換成叠代器。

  (5)python 的for 循環本質上就是通過不斷調用next函數實現的。

四、python中的內置方法

  參考:https://docs.python.org/3/library/functions.html?highlight=built#ascii

  技術分享圖片

  下面針對一些常用的內置方法進行解釋

1、all(iterable) : 如果可叠代對象中的所有元素都為真,則返回True

print(all([-1,2,1,mr]))

2、any(iterable) :如果可叠代對象中的任意元素為真,則返回True

print(any([0,1,2,3]))

3、ascii(object) :以字符串的形式返回內容的ascii碼格式

a = ascii([1,2,3,MR,"你好"])
print(a)
print(type(a),[a])

4、bin(x) : 把十進制數字轉換為二進制數字

print( bin(4) )

5、bool() :判斷bool類型(非零即真)

print(bool(1))
print(bool([]))

6、bytearray([source[,encoding[,errors]]]) :返回一個新字節數組。這個數組裏的元素是可變的,並且每個元素的值範圍: 0 <= x < 256。

#字符串不可以修改,只是生成一個新的字符串;二進制的字符格式也不可以修改
a = bytes(abcde,encoding=utf-8)
print(a.capitalize())
print(a)
b = bytearray(abcde,encoding=utf-8)
print( b[1] )
b[1] = 50 # 只能賦值ascii碼的類型
print(b)

7、callable() : 是否可調用(可以加括號的就可以調用,比如函數和類)

print(callable([]))
def func1():
    pass
print(callable(func1))

8、chr(i) :輸入數字,返回ascii碼的對應表

print(chr(97))

9、ord() : 輸入ascii碼字符,返回對應的數字

print(ord(a))

10、complex([real[,imag]]) : 返回一個復數

print(complex(1,2))

11、dir : 查看對應的方法

a = []
print(dir(a))

12、divmod(a,b) : 地板除(返回整數部分和余數部分)

print(divmod(10,3))
>>>(3,1)

13、eval(source[, globals[, locals]]) : 將字符串str當成有效的表達式來求值並返回計算結果。參數:source:一個Python表達式或函數compile()返回的代碼對象;globals:可選。必須是dictionary;locals:可選。任意map對象。

a = "[[1,2],[3,4]]"
b = eval(a)
print(b)
>>>[[1, 2], [3, 4]]

14、filter(function, iterable) : 過濾出需要的內容

res = filter(lambda n : n>5 ,range(10))
for i in res:
    print(i)

15、map() : 根據提供的函數對指定序列做映射。

  第一個參數 function 以參數序列中的每一個元素調用 function 函數,返回包含每次 function 函數返回值的新列表。

res = map(lambda n: n*n, range(10))
for i in res:
    print(i)
print(type(res))
>>>

0
1
4
9
16
25
36
49
64
81

16、reduce() : 函數會對參數序列中元素進行累積。

  函數將一個數據集合(鏈表,元組等)中的所有數據進行下列操作:用傳給reduce中的函數 function(有兩個參數)先對集合中的第 1、2 個元素進行操作,得到的結果再與第三個數據用 function 函數運算,最後得到一個結果。

from functools import reduce
res = reduce(lambda x, y : x+y, range(10))
print(res)
>>>45

17、format() : 格式化函數

name = input("name:")
age = input ("age:")
job = input ("job:")

info ="""
Name :{_name}
Age: {_age}
Job :{_job}

""" .format(_name=name,_age = age, _job = job)

print (info)

18、frozenset([iterable]) : 凍結集合(使集合無法修改)

a = frozenset([1,2,3,2,1,42,546,6])
print(a.add(7))
>>>AttributeError: ‘frozenset‘ object has no attribute ‘add‘

19、globals() : 函數會以字典類型返回當前位置的全部全局變量。

a = frozenset([1,2,3,4,5,6])
print(globals())

20、locals() : 函數會以字典類型返回當前位置的全部局部變量。

def test():
    local_var = 333
    print(locals())
test()
print(globals())
print(globals().get(local_var))

21、hash() :用於獲取取一個對象(字符串或者數值等)的哈希值。

print(hash(a))
>>>

1164304272

22、hex() : 轉換為十六進制

print(hex(15))

23、oct(x) : 轉換為八進制

print(oct(9))

24、id(object) : 返回內存地址

print(id(a))

25、max() / min() : 取最大/最小值

a = [1,2,5,6,3]
print(max(a))
print(min(a))

26、pow(a,b): 返回 a 的 b次方

print(pow(2,4))

27、round(a,b) : 將 a 保留 b 位小數

print(round(1.3333, 2))
>>>1.33

28、slice() : 切片

myslice = slice(5)
a = [x for  x in range(10)]
print(a[myslice])
>>>[0, 1, 2, 3, 4]

29、sorted() : 排序

a = [1,4,2,5,23,6,7,4,2]
print(a)
print(sorted(a))
b = {2:two, 1:one, 4:four, 7:seven}
print(b)
print(sorted(b.items())) # 以key為目標排序,結果是一個列表
print(sorted(b.items(), key = lambda x : x[1])) # 以value為目標排序
>>>

[1, 4, 2, 5, 23, 6, 7, 4, 2]
[1, 2, 2, 4, 4, 5, 6, 7, 23]
{1: ‘one‘, 2: ‘two‘, 4: ‘four‘, 7: ‘seven‘}
[(1, ‘one‘), (2, ‘two‘), (4, ‘four‘), (7, ‘seven‘)]
[(4, ‘four‘), (1, ‘one‘), (7, ‘seven‘), (2, ‘two‘)]



30、zip : 按照最少的內容進行組合

a = [1,2,3,4,5]
b = [a,b,c,d]
c = [one,two,three,four]
for i in zip(a,b,c):
    print(i)
>>>

(1, ‘a‘, ‘one‘)
(2, ‘b‘, ‘two‘)
(3, ‘c‘, ‘three‘)
(4, ‘d‘, ‘four‘)

五、json & pickle 的數據序列化及反序列化

1、json模塊:用於字符串和python數據類型之間的轉換

  四個功能:dump, dumps, load, loads

示例1:把字典寫入文件中

(1)普通方法

info = {
    name : MR,
    age: 18
}

f = open("info.txt",w)
f.write(str(info))

(2)json序列化

import json

info = {
    name : MR,
    age: 18
}
f = open(info.txt,w)
f.write( json.dumps( info ))

示例2:把文件中的內容讀取出來

(1)普通方法

f = open("info.txt",r)
data = eval(f.read())
print(data[age])

f.close()

(2)json反序列化

import json
f = open(info.txt,r)
data = json.loads(f.read())
print(data[age])

2、pickle模塊: 用於python特有的類型和python的數據類型之間的轉換

  四個功能:dump, dumps, load, loads

示例1:把字典寫入文件中

  pickle序列化:

import pickle

info = {
    name : MR,
    age: 18
}

f = open(info.txt,wb)
f.write( pickle.dumps( info )) # pickle.dumps 會把原數據類型變為二進制類型。
# f.write( pickle.dumps( info )) == pickle.dump(info, f)

示例2:把文件中的內容讀取出來

  pickle反序列化:

import pickle
f = open(info.txt,rb)
data = pickle.loads(f.read())  #  == data = pickle.load(f)
print(data[age])

六、程序目錄結構規範

  引用自:https://www.cnblogs.com/alex3714/articles/5765046.html

  技術分享圖片

解釋:

1、bin/: 存放項目的一些可執行文件,當然可以起名script/之類的也行。

2、foo/: 存放項目的所有源代碼。(1) 源代碼中的所有模塊、包都應該放在此目錄。不要置於頂層目錄。(2) 其子目錄tests/存放單元測試代碼; (3) 程序的入口最好命名為main.py

3、docs/: 存放一些文檔

4、setup.py: 安裝、部署、打包的腳本。

5、requirements.txt: 存放軟件依賴的外部Python包列表。

6、readme: 項目說明文件。

七、補充內容:

(1)lambda() 函數

  lambda表達式,通常是在需要一個函數,但是又不想費神去命名一個函數的場合下使用,也就是指匿名函數。

a = lambda x,y: x+y
print(a(2,3))

(2)try-except 語句

基本語法:

try:
    檢測範圍
except Exception [as reason]:
    出現異常(Exception)後處理的代碼

示例:

try:
    int (abc)
    sum = 1 + 1
    f = open (我為啥是一個文件.txt)
    print(f.read())
    f.close()
except OSError as reason:
    print(文件出錯\n 錯誤的原因是: + str(reason))
except TypeError as reason:
    print(類型出錯\n 錯誤的原因是: + str(reason))
except ValueError as reason:
    print(值出錯\n 錯誤的原因是: + str(reason))

註意:try 語句一旦檢測到異常,後面的語句就不會被執行

(3)try-finally

解釋:基本用法與try-except 相似,只是finally 之後的代碼無論怎麽樣都會執行,可以try-except-finaaly 連用,這樣如果try中沒有異常,則會跳過except,直接執行finally 裏面的代碼

python 3.5學習筆記(第四章)