class MyClass: def __init__(self): print "initialize..." def __play(self): print "play..." a = MyClass()initialize... a._MyClass__play()play... dir(a)['_MyClass__play', '__doc__', '__init__', '__module__']python的私有是偽的,還是可以訪問到。 方法就是_類名__方法名,python不過是在以__開頭的方法名面前加了小動作導致訪問不到看起來像私有方法。

成都創(chuàng)新互聯(lián)公司10多年企業(yè)網(wǎng)站制作服務(wù);為您提供網(wǎng)站建設(shè),網(wǎng)站制作,網(wǎng)頁設(shè)計及高端網(wǎng)站定制服務(wù),企業(yè)網(wǎng)站制作及推廣,對木包裝箱等多個行業(yè)擁有多年的網(wǎng)站營銷經(jīng)驗的網(wǎng)站建設(shè)公司。
python中函數(shù)和方法的區(qū)別:
首先,從分類的角度來分析。
(1)函數(shù)的分類:
內(nèi)置函數(shù):python內(nèi)嵌的一些函數(shù)。
匿名函數(shù):一行代碼實現(xiàn)一個函數(shù)功能。
遞歸函數(shù)
自定義函數(shù):根據(jù)自己的需求,來進行定義函數(shù)。
(2)方法的分類:
普通方法:直接用self調(diào)用的方法。
私有方法:__函數(shù)名,只能在類中被調(diào)用的方法。
屬性方法:@property,將方法偽裝成為屬性,讓代碼看起來更合理。
特殊方法(雙下劃線方法):以__init__為例,是用來封裝實例化對象的屬性,只要是實例化對象就一定會執(zhí)行__init方法,如果對象子類中沒有則會尋找父類(超類),如果父類(超類)也沒有,則直接繼承object(python 3.x)類,執(zhí)行類中的__init__方法。
類方法:通過類名的調(diào)用去操作公共模板中的屬性和方法。
靜態(tài)方法:不用傳入類空間、對象的方法, 作用是保證代碼的一致性,規(guī)范性,可以完全獨立類外的一個方法,但是為了代碼的一致性統(tǒng)一的放到某個模塊(py文件)中。
其次,從作用域的角度來分析:
(1)函數(shù)作用域:從函數(shù)調(diào)用開始至函數(shù)執(zhí)行完成,返回給調(diào)用者后,在執(zhí)行過程中開辟的空間會自動釋放,也就是說函數(shù)執(zhí)行完成后,函數(shù)體內(nèi)部通過賦值等方式修改變量的值不會保留,會隨著返回給調(diào)用者后,開辟的空間會自動釋放。
(2)方法作用域:通過實例化的對象進行方法的調(diào)用,調(diào)用后開辟的空間不會釋放,也就是說調(diào)用方法中對變量的修改值會一直保留。
最后,調(diào)用的方式不同。
(1)函數(shù):通過“函數(shù)名()”的方式進行調(diào)用。
(2)方法:通過“對象.方法名”的方式進行調(diào)用。
class Foo(object): ? ?def func(self): ? ? ? ?pass#實例化obj = Foo()# 執(zhí)行方式一:調(diào)用的func是方法obj.func() #func 方法# 執(zhí)行方式二:調(diào)用的func是函數(shù)Foo.func(123) # 函數(shù)
你這個代碼很有問題,
1. class Student:
def __init__(self):
for name in Name:
for id in ID:
self.name = name
self.id = id
最終Student得到的是實例有兩個變量name和id,他們的值分別是Kay和3,初始化時候的遍歷完全沒有意義。
2. self.lst.append("{} of {}".format(Student.__init__(self.id), Student.__init__(self.name)))
Student是一個類型,你都沒創(chuàng)建一個實例,__init__是實例的初始化函數(shù),使用"__"修飾,是私有函數(shù),不能在外部調(diào)用,然后那個里面參數(shù)的self是Students的self肯定是訪問不到id和name的屬性的。
總的來說,代碼存在很多的問題。
想要獲得的結(jié)果是兩個列表中元素所有組合的可能性,可以這樣實現(xiàn):
Name = ['Stella','Kay']
ID = [1,3]
result = [(a, b) for a in ID for b in Name]
這樣得到的result就是兩個列表的元素的組合
不是使用property才要私有的,而是為了調(diào)用私有方法方便,才使用property的,具體請看下面的詳解
在綁定屬性時,如果直接把屬性暴露出去,雖然寫起來很簡單,但是,沒辦法檢查參數(shù),導致可以把成績隨便改:
s?=?Student()
s.score?=?9999
這顯然不合邏輯。為了限制score的范圍,可以通過一個set_score()方法來設(shè)置成績,再通過一個get_score()來獲取成績,這樣,在set_score()方法里,就可以檢查參數(shù):
class?Student(object):
def?get_score(self):
return?self._score
def?set_score(self,?value):
if?not?isinstance(value,?int):
raise?ValueError('score?must?be?an?integer!')
if?value??0?or?value??100:
raise?ValueError('score?must?between?0?~?100!')
self._score?=?value
現(xiàn)在,對任意的Student實例進行操作,就不能隨心所欲地設(shè)置score了:
s?=?Student()
s.set_score(60)?#?ok!
s.get_score()
60
s.set_score(9999)
Traceback?(most?recent?call?last):
...
ValueError:?score?must?between?0?~?100!
但是,上面的調(diào)用方法又略顯復(fù)雜,沒有直接用屬性這么直接簡單。
有沒有既能檢查參數(shù),又可以用類似屬性這樣簡單的方式來訪問類的變量呢?對于追求完美的Python程序員來說,這是必須要做到的!
還記得裝飾器(decorator)可以給函數(shù)動態(tài)加上功能嗎?對于類的方法,裝飾器一樣起作用。Python內(nèi)置的@property裝飾器就是負責把一個方法變成屬性調(diào)用的:
class Student(object):
@property
def?score(self):
return?self._score
@score.setter
def?score(self,?value):
if?not?isinstance(value,?int):
raise?ValueError('score?must?be?an?integer!')
if?value??0?or?value??100:
raise?ValueError('score?must?between?0?~?100!')
self._score?=?value
@property的實現(xiàn)比較復(fù)雜,先考察如何使用。把一個getter方法變成屬性,只需要加上@property就可以了,此時,@property本身又創(chuàng)建了另一個裝飾器@score.setter,負責把一個setter方法變成屬性賦值,于是,就擁有一個可控的屬性操作:
s?=?Student()
s.score?=?60?#?OK,實際轉(zhuǎn)化為s.set_score(60)
s.score?#?OK,實際轉(zhuǎn)化為s.get_score()
60
s.score?=?9999
Traceback?(most?recent?call?last):
...
ValueError:?score?must?between?0?~?100!
注意到這個神奇的@property,在對實例屬性操作的時候,就知道該屬性很可能不是直接暴露的,而是通過getter和setter方法來實現(xiàn)的。
還可以定義只讀屬性,只定義getter方法,不定義setter方法就是一個只讀屬性:
class?Student(object):
@property
def?birth(self):
return?self._birth
@birth.setter
def?birth(self,?value):
self._birth?=?value
@property
def?age(self):
return?2014?-?self._birth
上面的birth是可讀寫屬性,而age就是一個只讀屬性,因為age可以根據(jù)birth和當前時間計算出來。
一句話總結(jié)
@property廣泛應(yīng)用在類的定義中,可以讓調(diào)用者寫出簡短的代碼,同時保證對參數(shù)進行必要的檢查,這樣,程序運行時就減少了出錯的可能性。
9.6. 私有變量
只能從對像內(nèi)部訪問的“私有”實例變量,在 Python 中不存在。然而,也有一個變通的訪問用于大多數(shù) Python 代碼:以一個下劃線開頭的命名(例如 _spam )會被處理為 API 的非公開部分(無論它是一個函數(shù)、方法或數(shù)據(jù)成員)。它會被視為一個實現(xiàn)細節(jié),無需公開。
因為有一個正當?shù)念愃接谐蓡T用途(即避免子類里定義的命名與之沖突),Python 提供了對這種結(jié)構(gòu)的有限支持,稱為 name mangling (命名編碼) 。任何形如 __spam 的標識(前面至少兩個下劃線,后面至多一個),被替代為 _classname__spam ,去掉前導下劃線的 classname 即當前的類名。此語法不關(guān)注標識的位置,只要求在類定義內(nèi)。
名稱重整是有助于子類重寫方法,而不會打破組內(nèi)的方法調(diào)用。例如:
class Mapping:
def __init__(self, iterable):
self.items_list = []
self.__update(iterable)
def update(self, iterable):
for item in iterable:
self.items_list.append(item)
__update = update # private copy of original update() method
class MappingSubclass(Mapping):
def update(self, keys, values):
# provides new signature for update()
# but does not break __init__()
for item in zip(keys, values):
self.items_list.append(item)
需要注意的是編碼規(guī)則設(shè)計為盡可能的避免沖突,被認作為私有的變量仍然有可能被訪問或修改。在特定的場合它也是有用的,比如調(diào)試的時候。
要注意的是代碼傳入 exec(), eval() 時不考慮所調(diào)用的類的類名,視其為當前類,這類似于 global 語句的效應(yīng),已經(jīng)按字節(jié)編譯的部分也有同樣的限制。這也同樣作用于 getattr(), setattr() 和 delattr(),像直接引用 __dict__ 一樣。
標題名稱:關(guān)于python私有函數(shù)實現(xiàn)的信息
鏈接分享:http://chinadenli.net/article3/dsegcos.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供軟件開發(fā)、域名注冊、定制網(wǎng)站、網(wǎng)站設(shè)計、建站公司、網(wǎng)頁設(shè)計公司
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)