在這里我們來看看Python提供的一些高級功能。
在此將著眼于Python如何利用類中的操作符。 Python很大程度上是對象和方法調(diào)用對象,甚至當(dāng)它隱藏在一些方便的語法中時,它甚至?xí)^續(xù)執(zhí)行。
>>> var1 = 'Hello'
>>> var2 = ' World!'
>>> var1 + var2
'Hello World!'
>>>
>>> var1.__add__(var2)
'Hello World!'
>>> num1 = 45
>>> num2 = 60
>>> num1.__add__(num2)
105
>>> var3 = ['a', 'b']
>>> var4 = ['hello', ' John']
>>> var3.__add__(var4)
['a', 'b', 'hello', ' John']
所以如果我們必須將魔術(shù)方法__add__添加到自己的類中,是不是也可以這么做。現(xiàn)在,我們可以試著去做。
假設(shè)有一個名為Sumlist的類,它有一個構(gòu)造函數(shù)__init__,它將list作為名為my_list的參數(shù)。
class SumList(object):
def __init__(self, my_list):
self.mylist = my_list
def __add__(self, other):
new_list = [ x + y for x, y in zip(self.mylist, other.mylist)]
return SumList(new_list)
def __repr__(self):
return str(self.mylist)
aa = SumList([3,6, 9, 12, 15])
bb = SumList([100, 200, 300, 400, 500])
cc = aa + bb # aa.__add__(bb)
print(cc) # should gives us a list ([103, 206, 309, 412, 515])
執(zhí)行上面示例代碼,得到以下結(jié)果 -
[103, 206, 309, 412, 515]
但有很多方法是由其他魔術(shù)方法內(nèi)部管理的。 下面是其中的一些,
'abc' in var # var.__contains__('abc')
var == 'abc' # var.__eq__('abc')
var[1] # var.__getitem__(1)
var[1:3] # var.__getslice__(1, 3)
len(var) # var.__len__()
print(var) # var.__repr__()
類還可以從內(nèi)置類型繼承,這意味著從任何內(nèi)置繼承,并利用其中找到的所有功能。
在下面的例子中,從字典繼承,并實現(xiàn)它的一個方法__setitem__。 這個(setitem)在設(shè)置字典中的鍵和值時被調(diào)用。 因為這是一種神奇的方法,所以這將被隱式地調(diào)用。
class MyDict(dict):
def __setitem__(self, key, val):
print('setting a key and value!')
dict.__setitem__(self, key, val)
dd = MyDict()
dd['a'] = 10
dd['b'] = 20
for key in dd.keys():
print('{0} = {1}'.format(key, dd[key]))
執(zhí)行上面示例代碼,得到以下結(jié)果 -
setting a key and value!
setting a key and value!
a = 10
b = 20
繼續(xù)前面的例子,下面在處理列表索引時調(diào)用了兩個名為__getitem__和__setitem__的魔術(shù)方法。
# Mylist inherits from 'list' object but indexes from 1 instead for 0!
class Mylist(list): # inherits from list
def __getitem__(self, index):
if index == 0:
raise IndexError
if index > 0:
index = index - 1
return list.__getitem__(self, index) # this method is called when
# we access a value with subscript like x[1]
def __setitem__(self, index, value):
if index == 0:
raise IndexError
if index > 0:
index = index - 1
list.__setitem__(self, index, value)
x = Mylist(['a', 'b', 'c']) # __init__() inherited from builtin list
print(x) # __repr__() inherited from builtin list
x.append('HELLO'); # append() inherited from builtin list
print(x[1]) # 'a' (Mylist.__getitem__ cutomizes list superclass
# method. index is 1, but reflects 0!
print (x[4]) # 'HELLO' (index is 4 but reflects 3!
執(zhí)行上面示例代碼,得到以下結(jié)果 -
['a', 'b', 'c']
a
HELLO
在上面的例子中,在Mylist中設(shè)置了三個項目列表,并隱式調(diào)用__init__方法,當(dāng)打印元素x時,我們得到三個項目列表(['a','b','c'])。 然后在這個列表中追加另一個元素。 后來打印索引1和索引4。如果看到從(索引-1)中獲得所要求的元素。 我們知道,列表索引從0開始,但這里索引從1開始(這就是為什么要得到是列表的第一項)。
在這里,我們將查看用于變量的名稱,特別是全局Python程序員使用的私有變量和約定。 盡管變量被指定為私有,但在Python中并沒有隱私,并且這是按設(shè)計的。 和任何其他有良好記錄的語言一樣,Python具有它提出的命名和樣式約定,盡管它沒有強(qiáng)制執(zhí)行它們。 有一個由“Guido van Rossum”編寫的Python風(fēng)格指南,它描述了最佳實踐和名稱的使用,被稱為PEP8。 這里是這個鏈接,https://www.python.org/dev/peps/pep-0008/
PEP代表Python增強(qiáng)提議,并且是一系列在Python社區(qū)中分發(fā)以討論提議的更改的文檔。 例如,建議所有人,
這些只是推薦,如果你喜歡,可以根據(jù)需要改變。 但是,由于大多數(shù)開發(fā)人員遵循這些建議,那么可能代碼很容易閱讀。
可以遵循允許獲得的PEP建議,
在Python中,當(dāng)處理模塊和類時,將一些變量或?qū)傩灾付樗接小?在Python中,除了在對象內(nèi)部之外,不存在“私有”實例變量。 私有僅僅意味著它們根本不打算被代碼的用戶使用,而是打算在內(nèi)部使用。 一般來說,大多數(shù)Python開發(fā)人員都遵循一個約定,例如,名稱前面加上一個下劃線。_attrval(下面的示例)應(yīng)該被視為API或任何Python代碼的非公開部分,無論它是函數(shù),方法還是數(shù)據(jù)成員。 以下是遵循的命名約定,
regular_lower_case_single_leading_underscore__ double_leading_underscore__ double_underscores __(使用它們,不要創(chuàng)建它們)class GetSet(object):
instance_count = 0 # public
__mangled_name = 'no privacy!' # special variable
def __init__(self, value):
self._attrval = value # _attrval is for internal use only
GetSet.instance_count += 1
@property
def var(self):
print('Getting the "var" attribute')
return self._attrval
@var.setter
def var(self, value):
print('setting the "var" attribute')
self._attrval = value
@var.deleter
def var(self):
print('deleting the "var" attribute')
self._attrval = None
cc = GetSet(5)
cc.var = 10 # public name
print(cc._attrval)
print(cc._GetSet__mangled_name)
執(zhí)行上面示例代碼,得到以下結(jié)果 -
setting the "var" attribute
10
no privacy!