Day 01——Task01:變量、運算符與數據類型
Day 02——Task02:條件與循環
Day 03——Task03:列表與元組(上)
Day 04——Task03:列表與元組(下)
Day 05——Task04:字符串與序列
Day 06——Task05:函數與Lambda表達式(上)
Day 07——Task05:函數與Lambda表達式(下)
Day 08——Task06:字典與集合
Day 09——Task07:文件與文件系統(上)
Day 10——Task07:文件與文件系統(下)
Day 11——Task08:異常處理
Day 12——Task09:else 與 with 語句
Day 13——Task10:類與對象(上)
Day 14——Task10:類與對象(下)
Day 15——Task11:魔法方法(上)
Day 16——Task11:魔法方法(下)
Day 17——Task12:模塊
2.魔法方法
2.6. 屬性訪問
__getattr__
,__getattribute__
,__setattr__
和__delattr__
__getattr__(self, name)
: 定義當用戶試圖獲取一個不存在的屬性時的行爲。
__getattribute__(self, name)
:定義當該類的屬性被訪問時的行爲(先調用該方法,查看是否存在該屬性,若不存在,接着去調用__getattr__
)。
__setattr__(self, name, value)
:定義當一個屬性被設置時的行爲。
__delattr__(self, name)
:定義當一個屬性被刪除時的行爲。
class C:
def __getattribute__(self, item):
print('__getattribute__')
return super().__getattribute__(item)
def __getattr__(self, item):
print('__getattr__')
def __setattr__(self, key, value):
print('__setattr__')
super().__setattr__(key, value)
def __delattr__(self, item):
print('__delattr__')
super().__delattr__(item)
c = C()
c.x
# __getattribute__
# __getattr__
c.x = 1
# __setattr__
del c.x
# __delattr__
2.7. 描述符
描述符就是將某種特殊類型的類的實例指派給另一個類的屬性。
__get__(self, instance, owner)
用於訪問屬性,它返回屬性的值。__set__(self, instance, value)
將在屬性分配操作中調用,不返回任何內容。__del__(self, instance)
控制刪除操作,不返回任何內容。
class MyDecriptor:
def __get__(self, instance, owner):
print('__get__', self, instance, owner)
def __set__(self, instance, value):
print('__set__', self, instance, value)
def __delete__(self, instance):
print('__delete__', self, instance)
class Test:
x = MyDecriptor()
t = Test()
t.x
# __get__ <__main__.MyDecriptor object at 0x000000CEAAEB6B00> <__main__.Test object at 0x000000CEABDC0898> <class '__main__.Test'>
t.x = 'x-man'
# __set__ <__main__.MyDecriptor object at 0x00000023687C6B00> <__main__.Test object at 0x00000023696B0940> x-man
del t.x
# __delete__ <__main__.MyDecriptor object at 0x000000EC9B160A90> <__main__.Test object at 0x000000EC9B160B38>
2.8. 定製序列
協議(Protocols)與其它編程語言中的接口很相似,它規定你哪些方法必須要定義。然而,在 Python 中的協議就顯得不那麼正式。事實上,在 Python 中,協議更像是一種指南。
容器類型的協議
如果說你希望定製的容器是不可變的話,你只需要定義__len__()
和__getitem__()
方法。
如果你希望定製的容器是可變的話,除了__len__()
和__getitem__()
方法,你還需要定義__setitem__()
和__delitem__()
兩個方法。
編寫一個不可改變的自定義列表,要求記錄列表中每個元素被訪問的次數。
class CountList:
def __init__(self, *args):
self.values = [x for x in args]
self.count = {}.fromkeys(range(len(self.values)), 0)
def __len__(self):
return len(self.values)
def __getitem__(self, item):
self.count[item] += 1
return self.values[item]
c1 = CountList(1, 3, 5, 7, 9)
c2 = CountList(2, 4, 6, 8, 10)
print(c1[1]) # 3
print(c2[2]) # 6
print(c1[1] + c2[1]) # 7
print(c1.count)
# {0: 0, 1: 2, 2: 0, 3: 0, 4: 0}
print(c2.count)
# {0: 0, 1: 1, 2: 1, 3: 0, 4: 0}
__len__(self)
定義當被len()調用時的行爲(返回容器中元素的個數)。__getitem(self, key)
定義獲取容器中元素的行爲,相當於self[key]
。__setitem(self, key, value)
定義設置容器中指定元素的行爲,相當於self[key] = value
。__delitem(self, key)
定義刪除容器中指定元素的行爲,相當於del self[key]
。
編寫一個可改變的自定義列表,要求記錄列表中每個元素被訪問的次數。
class CountList:
def __init__(self, *args):
self.values = [x for x in args]
self.count = {}.fromkeys(range(len(self.values)), 0)
def __len__(self):
return len(self.values)
def __getitem__(self, item):
self.count[item] += 1
return self.values[item]
def __setitem__(self, key, value):
self.values[key] = value
def __delitem__(self, key):
del self.values[key]
for i in range(0, len(self.values)):
if i >= key:
self.count[i] = self.count[i + 1]
self.count.pop(len(self.values))
c1 = CountList(1, 3, 5, 7, 9)
c2 = CountList(2, 4, 6, 8, 10)
print(c1[1]) # 3
print(c2[2]) # 6
c2[2] = 12
print(c1[1] + c2[2]) # 15
print(c1.count)
# {0: 0, 1: 2, 2: 0, 3: 0, 4: 0}
print(c2.count)
# {0: 0, 1: 0, 2: 2, 3: 0, 4: 0}
del c1[1]
print(c1.count)
# {0: 0, 1: 0, 2: 0, 3: 0}
2.9. 迭代器
- 迭代是 Python 最強大的功能之一,是訪問集合元素的一種方式。
- 迭代器是一個可以記住遍歷的位置的對象。
- 迭代器對象從集合的第一個元素開始訪問,直到所有的元素被訪問完結束。
- 迭代器只能往前不會後退。
- 字符串,列表或元組對象都可用於創建迭代器
舉一個栗子~
string = 'lsgogroup'
for c in string:
print(c)
'''
l
s
g
o
g
r
o
u
p
'''
for c in iter(string):
print(c)
再來個栗子~
links = {'B': '百度', 'A': '阿里', 'T': '騰訊'}
for each in links:
print('%s -> %s' % (each, links[each]))
'''
B -> 百度
A -> 阿里
T -> 騰訊
'''
for each in iter(links):
print('%s -> %s' % (each, links[each]))
- 迭代器有兩個基本的方法:
iter()
和next()
。 iter(object)
函數用來生成迭代器。next(iterator[, default])
返回迭代器的下一個項目。iterator
– 可迭代對象default
– 可選,用於設置在沒有下一個元素時返回該默認值,如果不設置,又沒有下一個元素則會觸發StopIteration
異常。
links = {'B': '百度', 'A': '阿里', 'T': '騰訊'}
it = iter(links)
print(next(it)) # B
print(next(it)) # A
print(next(it)) # T
print(next(it)) # StopIteration
it = iter(links)
while True:
try:
each = next(it)
except StopIteration:
break
print(each)
# B
# A
# T
把一個類作爲一個迭代器使用需要在類中實現兩個魔法方法 __iter__()
與 __next__()
。
__iter__(self)
定義當迭代容器中的元素的行爲,返回一個特殊的迭代器對象, 這個迭代器對象實現了__next__()
方法並通過 StopIteration 異常標識迭代的完成。__next__()
返回下一個迭代器對象。StopIteration
異常用於標識迭代的完成,防止出現無限循環的情況,在__next__()
方法中我們可以設置在完成指定循環次數後觸發StopIteration
異常來結束迭代。
class Fibs:
def __init__(self, n=10):
self.a = 0
self.b = 1
self.n = n
def __iter__(self):
return self
def __next__(self):
self.a, self.b = self.b, self.a + self.b
if self.a > self.n:
raise StopIteration
return self.a
fibs = Fibs(100)
for each in fibs:
print(each, end=' ')
# 1 1 2 3 5 8 13 21 34 55 89
2.10. 生成器
- 在 Python 中,使用了
yield
的函數被稱爲生成器(generator)。 - 跟普通函數不同的是,生成器是一個返回迭代器的函數,只能用於迭代操作,更簡單點理解生成器就是一個迭代器。
- 在調用生成器運行的過程中,每次遇到 yield 時函數會暫停並保存當前所有的運行信息,返回
yield
的值, 並在下一次執行next()
方法時從當前位置繼續運行。 - 調用一個生成器函數,返回的是一個迭代器對象。
def myGen():
print('生成器執行!')
yield 1
yield 2
myG = myGen()
print(next(myG))
# 生成器執行!
# 1
print(next(myG)) # 2
print(next(myG)) # StopIteration
myG = myGen()
for each in myG:
print(each)
'''
生成器執行!
1
2
'''
用生成器實現斐波那契數列。
def libs(n):
a = 0
b = 1
while True:
a, b = b, a + b
if a > n:
return
yield a
for each in libs(100):
print(each, end=' ')
# 1 1 2 3 5 8 13 21 34 55 89
2.11. 推導式
列表推導式
a = [i for i in range(100) if (i % 2) != 0 and (i % 3) == 0]
print(a)
# [3, 9, 15, 21, 27, 33, 39, 45, 51, 57, 63, 69, 75, 81, 87, 93, 99]
字典推導式
b = {i: i % 2 == 0 for i in range(10) if i % 3 == 0}
print(b)
# {0: True, 3: False, 6: True, 9: False}
集合推導式
c = {i for i in [1, 2, 3, 4, 5, 5, 6, 4, 3, 2, 1]}
print(c)
# {1, 2, 3, 4, 5, 6}
其它
d = 'i for i in "I Love Lsgogroup"'
print(d)
# i for i in "I Love Lsgogroup"
e = (i for i in range(10))
print(e)
# <generator object <genexpr> at 0x0000007A0B8D01B0>
print(next(e)) # 0
print(next(e)) # 1
for each in e:
print(each, end=' ')
# 2 3 4 5 6 7 8 9
s = sum([i for i in range(101)])
print(s) # 5050
s = sum((i for i in range(101)))
print(s) # 5050
參考資料
- https://blog.csdn.net/LSGO_MYP/article/details/102887712
- https://www.runoob.com/python3/python3-tutorial.html
- https://www.bilibili.com/video/av4050443
- http://c.biancheng.net/view/2371.html
- https://www.cnblogs.com/seablog/p/7173107.html
- https://www.cnblogs.com/Jimmy1988/p/6804095.html
- https://blog.csdn.net/johnsonguo/article/details/585193