在Python中,如果我們想實現(xiàn)創(chuàng)建類似于序列和映射的類(可以迭代以及通過[下標(biāo)]返回元素),可以通過重寫魔法方法__getitem__钱磅、__setitem__梦裂、__delitem__、__len__
方法去模擬盖淡。
魔術(shù)方法的作用:
__getitem__(self,key):
返回鍵對應(yīng)的值年柠。
__setitem__(self,key,value):
設(shè)置給定鍵的值
__delitem__(self,key):
刪除給定鍵對應(yīng)的元素。
__len__():
返回元素的數(shù)量
【注釋】只要實現(xiàn)了__getitem__
和 __len__
方法禁舷,就會被認(rèn)為是序列彪杉。
- 可以用
__len__():
函數(shù)來查看對象長度 -
__getitem__(self,key):
可以對對象進(jìn)行[]操作,如切片牵咙,索引派近,iterd等高級操作。 - 如果在類中定義了
__getitem__()
方法洁桌,那么他的實例對象(假設(shè)為P)就可以這樣P[key]取值渴丸。當(dāng)實例對象做P[key]運(yùn)算時,就會調(diào)用類中的__getitem__()
方法另凌。
這些魔術(shù)方法的原理就是:當(dāng)我們對類的屬性item進(jìn)行下標(biāo)的操作時谱轨,首先會被__getitem__()、__setitem__()吠谢、__delitem__()
攔截土童,從而執(zhí)行我們在方法中設(shè)定的操作,如賦值工坊,修改內(nèi)容献汗,刪除內(nèi)容等等。
這個方法應(yīng)該以與鍵相關(guān)聯(lián)的方式存儲值王污,以便之后能夠使用__setitem__
來獲取罢吃。當(dāng)然,這個對象可變時才需要實現(xiàn)這個方法昭齐。
舉個栗子:
定義一副撲克牌(不包括大小王)尿招,對牌進(jìn)行洗牌,然后發(fā)牌阱驾。
mport collections
Card = collections.namedtuple('Card',['rank','suit'])
#也可以使用一個類來定義Card
# class Card:
# def __init__(self,rank,suit):
# self.rank = rank
# self.suit = suit
class Puke:
ranks = [str(n) for n in range(2,11) ] + list('JQKA')
suits = "黑桃 方塊 梅花 紅心".split()
def __init__(self):
self._cards = [Card(rank,suit) for suit in self.suits for rank in self.ranks]
def __len__(self):
return len(self._cards)
def __getitem__(self, item):
return self._cards[item]
def __setitem__(self, key, value):
print(key,value)
self._cards[key] = value
pk = Puke()
# print(pk._cards)
# for card in pk:
print(card)
print(pk[2:6])
print(pk[12::13])
pk[1:3] = [Card(rank='A',suit='紅桃')] * 3
print(pk[1:3])
Output:
[Card(rank='2', suit='黑桃'), Card(rank='3', suit='黑桃'), Card(rank='4', suit='黑桃'), Card(rank='5', suit='黑桃'), Card(rank='6', suit='黑桃'), Card(rank='7', suit='黑桃'), Card(rank='8', suit='黑桃'), Card(rank='9', suit='黑桃'), Card(rank='10', suit='黑桃'), Card(rank='J', suit='黑桃'), Card(rank='Q', suit='黑桃'), Card(rank='K', suit='黑桃'), Card(rank='A', suit='黑桃'), Card(rank='2', suit='方塊'), Card(rank='3', suit='方塊'), Card(rank='4', suit='方塊'), Card(rank='5', suit='方塊'), Card(rank='6', suit='方塊'), Card(rank='7', suit='方塊'), Card(rank='8', suit='方塊'), Card(rank='9', suit='方塊'), Card(rank='10', suit='方塊'), Card(rank='J', suit='方塊'), Card(rank='Q', suit='方塊'), Card(rank='K', suit='方塊'), Card(rank='A', suit='方塊'), Card(rank='2', suit='梅花'), Card(rank='3', suit='梅花'), Card(rank='4', suit='梅花'), Card(rank='5', suit='梅花'), Card(rank='6', suit='梅花'), Card(rank='7', suit='梅花'), Card(rank='8', suit='梅花'), Card(rank='9', suit='梅花'), Card(rank='10', suit='梅花'), Card(rank='J', suit='梅花'), Card(rank='Q', suit='梅花'), Card(rank='K', suit='梅花'), Card(rank='A', suit='梅花'), Card(rank='2', suit='紅心'), Card(rank='3', suit='紅心'), Card(rank='4', suit='紅心'), Card(rank='5', suit='紅心'), Card(rank='6', suit='紅心'), Card(rank='7', suit='紅心'), Card(rank='8', suit='紅心'), Card(rank='9', suit='紅心'), Card(rank='10', suit='紅心'), Card(rank='J', suit='紅心'), Card(rank='Q', suit='紅心'), Card(rank='K', suit='紅心'), Card(rank='A', suit='紅心')]
[Card(rank='4', suit='黑桃'), Card(rank='5', suit='黑桃'), Card(rank='6', suit='黑桃'), Card(rank='7', suit='黑桃')]
[Card(rank='A', suit='黑桃'), Card(rank='A', suit='方塊'), Card(rank='A', suit='梅花'), Card(rank='A', suit='紅心')]
slice(1, 3, None) [Card(rank='A', suit='紅桃'), Card(rank='A', suit='紅桃'), Card(rank='A', suit='紅桃')]
[Card(rank='A', suit='紅桃'), Card(rank='A', suit='紅桃')]
【注意】
:我們會發(fā)現(xiàn)output中就谜,輸出了:slice(1, 3, None)
,下面給出解釋里覆。
切片原理
語法:
class slice(stop)
class slice(start, stop[, step])
參數(shù)說明:
- start -- 起始位置
- stop -- 結(jié)束位置
- step -- 間距
slice() 函數(shù)實現(xiàn)切片對象丧荐,主要用在切片操作函數(shù)里的參數(shù)傳遞。
slice用于規(guī)定序列的選取規(guī)則
舉兩個栗子來看看:
step = slice(0,5,2)
components = [11, 22, 66, 88, 99, 00, 123]
print(components[step])
Output:
[11, 66, 99]
切片原理
class MySeq:
def __getitem__(self, item):
return item
s = MySeq()
print(s[1])
print(s[1:4])
print(s[1:4:2])
print(s[1:4:2,7:9])
output
1
slice(1, 4, None)
slice(1, 4, 2)
(slice(1, 4, 2), slice(7, 9, None))
(程序員必會的 hhhhh.....)
看看slice在python3.7中是怎么描述的:
help(slice)
Help on class slice in module builtins:
class slice(object)
| slice(stop)
| slice(start, stop[, step])
|
| Create a slice object. This is used for extended slicing (e.g. a[0:10:2]).
|
| Methods defined here:
| 有點長租谈。。。忽略 ********
| ----------------------------------------------------------------------
| Static methods defined here:
|
| __new__(*args, **kwargs) from builtins.type
| Create and return a new object. See help(type) for accurate signature.
|
| ----------------------------------------------------------------------
| Data descriptors defined here:
|
| start
|
| step
|
| stop
|
| ----------------------------------------------------------------------
| Data and other attributes defined here:
|
| __hash__ = None