Python迭代器生成器,私有變數及列表字典集合推導式(二)

善良小郎君發表於2018-06-11

1 python自省機制

這個是python一大特性,自省就是物件導向的語言所寫的程式在執行時,能知道物件的型別,換句話說就是在執行時能獲取物件的型別,比如通過 type(),dir(),getattr(),hasattr(),isinstance().

a = [1,2,3]
b = {`a`:1,`b`:2,`c`:3}
c = True
print(type(a),type(b),type(c)) # <type `list`> <type `dict`> <type `bool`>
print(isinstance(a,list))  # True

2 python中列表推導式,字典推導式,集合推導式

列表生成式 : 中括號括起來表示列表

(1)[exp for iter_var in iterable if_exp]
#工作過程:
1 迭代iterable中的每個元素,每次迭代都先判斷if_exp表示式結果為真,如果為真則進行下一步,如果為假則進行下一次迭代;
2 把迭代結果賦值給iter_var,然後通過exp得到一個新的計算值;
3 最後把所有通過exp得到的計算值以一個新列表的形式返回。

#相當於這樣的過程:
L = []
for iter_var in iterable:
    if_exp:
        L.append(exp)

#也可以迴圈巢狀
(2)[exp for iter_var_A in iterable_A for iter_var_B in iterable_B]
工作過程:
每迭代iterable_A中的一個元素,就把ierable_B中的所有元素都迭代一遍。

#相當於這樣的過程:
L = []
for iter_var_A in iterable_A:
    for iter_var_B in iterable_B:
        L.append(exp)

字典推導式:大括號括起來,表示為字典

d = {key: value for (key, value) in iterable}

#快速更改字典key,value
mcase = {`a`: 10, `b`: 34}
mcase_frequency = {v: k for k, v in mcase.items()}
print(mcase_frequency)
#  Output: {10: `a`, 34: `b`}

集合推導式: 跟列表推導式也是類似的 唯一的區別在於它使用大括號{},表示結果為集合

squared = {x**2 for x in [1, 1, 2]}
print(squared)
# Output: set([1, 4])

3 Python中單下劃線和雙下劃線

>>> class MyClass():
...     def __init__(self):
...             self.__superprivate = "Hello"
...             self._semiprivate = ", world!"
...
>>> mc = MyClass()
>>> print(mc.__superprivate)  #私有變數不能直接訪問
    #print(mc._Myclass__superprivate)  也可以訪問,但是不建議這樣訪問
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: myClass instance has no attribute `__superprivate`
>>> print(mc._semiprivate)
, world!
>>> print(mc.__dict__)
{`_MyClass__superprivate`: `Hello`, `_semiprivate`: `, world!`}
  1. __foo__: 一種約定,Python內部的名字,用來區別其他使用者自定義的命名,以防衝突,就是例如__init__(),__del__(),__call__()這些特殊方法
  2. _foo: 一種約定,用來指定變數私有.程式設計師用來指定私有變數的一種方式.不能用from module import * 匯入,其他方面和公有一樣訪問;
  3. __foo: 意義: 私有變數不能直接訪問, 因為解析器用_classname__foo來代替這個名字,以區別和其他類相同的命名,它無法直接像公有成員一樣隨便訪問,但是可以通過物件名._類名__xxx這樣的方式可以訪問,但是不建議這樣來訪問.

4 字串格式化:%和.format

.format在許多方面看起來更便利.對於%最煩人的是它無法同時傳遞一個變數和元組.你可能會想下面的程式碼不會有什麼問題:

"hi there %s" % name

但是,如果name恰好是(1,2,3),它將會丟擲一個TypeError異常.為了保證它總是正確的,你必須這樣做:

"hi there %s" % (name,)   # 提供一個單元素的陣列而不是一個引數

但是有點醜 .format就沒有這些問題.而且format可以實現模運算子(%)不能做的事

tu = (12,45,22222,103,6)
print(`{0} {2} {1} {2} {3} {2} {4} {2}`.format(*tu))
#結果 12 22222 45 22222 103 22222 6 22222

另一點format()作為一個函式,可以用作其他函式的引數:

li = [12,45,78,784,2,69,1254,4785,984]
print(map(`the number is {}`.format,li))  

from datetime import datetime,timedelta
once_upon_a_time = datetime(2010, 7, 1, 12, 0, 0)
delta = timedelta(days=13, hours=8,  minutes=20)

gen =(once_upon_a_time + x*delta for x in xrange(20))

print `
`.join(map(`{:%Y-%m-%d %H:%M:%S}`.format, gen))

2010-07-01 12:00:00
2010-07-14 20:20:00
2010-07-28 04:40:00
2010-08-10 13:00:00
2010-08-23 21:20:00
2010-09-06 05:40:00
2010-09-19 14:00:00
2010-10-02 22:20:00
2010-10-16 06:40:00
2010-10-29 15:00:00
2010-11-11 23:20:00
2010-11-25 07:40:00
2010-12-08 16:00:00
2010-12-22 00:20:00
2011-01-04 08:40:00
2011-01-17 17:00:00
2011-01-31 01:20:00
2011-02-13 09:40:00
2011-02-26 18:00:00
2011-03-12 02:20:00

5 迭代器和生成器

​ 將列表生成式中[]改成() 之後資料結構發生改變 ,從列表變為生成器. 在for...in...語句中的都是可迭代的:比如lists,strings,files…因為這些可迭代的物件你可以隨意的讀取,所以非常方便易用,但是你必須把它們的值放到記憶體裡,當它們有很多值時就會消耗太多的記憶體.

>>> L = [x*x for x in range(10)]   #迭代器
>>> L
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]#列表
>>> g = (x*x for x in range(10))   #生成器
>>> g
<generator object <genexpr> at 0x0000028F8B774200>#生成器物件

​ 通過列表生成式,可以直接建立一個列表。但是受到記憶體限制,列表容量肯定是有限的。而且,建立一個包含百萬元素的列表,不僅是佔用很大的記憶體空間,如:我們只需要訪問前面的幾個元素,後面大部分元素所佔的空間都是浪費的。因此,沒有必要建立完整的列表(節省大量記憶體空間)。在Python中,我們可以採用生成器:邊迴圈,邊計算的機制—>generator

生成器的關鍵字yield: 理解Yield你必須先理解當你呼叫函式的時候,函式裡的程式碼並沒有執行.函式僅僅返回生成器物件

>>> def createGenerator():
...    mylist = range(3)
...    for i in mylist:
...        yield i*i
...
>>> mygenerator = createGenerator() # 建立生成器
>>> print(mygenerator) # mygenerator is an object!
<generator object createGenerator at 0xb7555c34>
>>> for i in mygenerator:
...     print(i)
0
1
4

當你的函式要返回一個非常大的集合並且你希望只讀一次的話,那麼它就非常的方便了.


相關文章