python 面向对象编程:类和实例
深度學(xué)習(xí)在構(gòu)建網(wǎng)絡(luò)模型時,看到用類來構(gòu)建一個模型實例,清晰明了,所以這篇博文主要學(xué)習(xí)一下python類
類和實例:
類可以起到模板的作用,因此,可以在創(chuàng)建實例的時候,把一些我們認(rèn)為必須綁定的屬性強制填寫進(jìn)去。通過定義一個特殊的__init__(注意:特殊方法“__init__”前后分別有兩個下劃線!!!),方法,在創(chuàng)建實例的時候,就把name,score等屬性綁上去:
class Student(object):def __init__(self, name, score):self.name = nameself.score = score__init__方法的第一個參數(shù)永遠(yuǎn)是self,表示創(chuàng)建的實例本身,因此,在__init__方法內(nèi)部,就可以把各種屬性綁定到self,因為self就指向創(chuàng)建的實例本身。有了__init__方法,創(chuàng)建實例的時候必須傳入與__init__方法匹配的參數(shù),self不需要傳,Python解釋器自己會把實例變量傳進(jìn)去:
>>> bart = Student('Bart Simpson', 59) >>> bart.name 'Bart Simpson'?和普通函數(shù)想比,類中定義的函數(shù)第一個參數(shù)永遠(yuǎn)是實例變量self,其他沒有什么不同。
訪問限制:
但是,從前面Student類的定義來看,外部代碼還是可以自由地修改一個實例的name、score屬性:
>>> bart = Student('Bart Simpson', 59) >>> bart.score 59 >>> bart.score = 99 >>> bart.score 99?如果在屬性的名稱前加上兩個下劃線__,在python中就是一個私有變量,只有內(nèi)部可以訪問,外部不能訪問,需要注意的是,在Python中,變量名類似__xxx__的,也就是以雙下劃線開頭,并且以雙下劃線結(jié)尾的,是特殊變量,特殊變量是可以直接訪問的,不是private變量,所以,不能用__name__、__score__這樣的變量名。
有些時候,你會看到以一個下劃線開頭的實例變量名,比如_name,這樣的實例變量外部是可以訪問的,但是,按照約定俗成的規(guī)定,當(dāng)你看到這樣的變量時,意思就是,“雖然我可以被訪問,但是,請把我視為私有變量,不要隨意訪問”。
雙下劃線開頭的實例變量是不是一定不能從外部訪問呢?其實也不是。不能直接訪問__name是因為Python解釋器對外把__name變量改成了_Student__name,所以,仍然可以通過_Student__name來訪問__name變量:
class Student(object):def __init__(self, name, score):self.__name = nameself.__score = scoredef print_score(self):print('%s: %s' % (self.__name, self.__score))>>> bart = Student('Bart Simpson', 59) >>> bart.__name Traceback (most recent call last):File "<stdin>", line 1, in <module> AttributeError: 'Student' object has no attribute '__name'>>> bart._Student__name 'Bart Simpson'但是強烈建議你不要這么干,因為不同版本的Python解釋器可能會把__name改成不同的變量名。
總的來說就是,Python本身沒有任何機制阻止你干壞事,一切全靠自覺。
最后注意下面的這種錯誤寫法,表面上看,外部代碼“成功”地設(shè)置了__name變量,但實際上這個__name變量和class內(nèi)部的__name變量不是一個變量!內(nèi)部的__name變量已經(jīng)被Python解釋器自動改成了_Student__name,而外部代碼給bart新增了一個__name變量:?
>>> bart = Student('Bart Simpson', 59) >>> bart.get_name() 'Bart Simpson' >>> bart.__name = 'New Name' # 設(shè)置__name變量! >>> bart.__name 'New Name'但是如果外部代碼要獲取name和score怎么辦?可以給Student類增加get_name和get_score這樣的方法;?如果又要允許外部代碼修改score怎么辦?可以再給Student類增加set_score方法:
class Student(object):...def get_name(self):return self.__namedef get_score(self):return self.__scoredef set_score(self, score):self.__score = score?數(shù)據(jù)封裝:
面向?qū)ο缶幊痰囊粋€重要特點就是數(shù)據(jù)封裝。在上面的Student類中,每個實例就擁有各自的name和score這些數(shù)據(jù)。我們可以通過函數(shù)來訪問這些數(shù)據(jù),比如打印一個學(xué)生的成績:
>>> def print_score(std): ... print('%s: %s' % (std.name, std.score)) ... >>> print_score(bart) Bart Simpson: 59?但是,既然Student實例本身就擁有這些數(shù)據(jù),要訪問這些數(shù)據(jù),就沒有必要從外面的函數(shù)去訪問,可以直接在Student類的內(nèi)部定義訪問數(shù)據(jù)的函數(shù)(如在上一部分中講到的獲取與修改數(shù)據(jù)的方法),我們稱之為類的方法,定義一個方法,除了第一個參數(shù)是self外,其他和普通函數(shù)一樣:
class Student(object):def __init__(self, name, score):self.name = nameself.score = scoredef print_score(self):print('%s: %s' % (self.name, self.score))實例屬性和類屬性?
由于python是動態(tài)語言,由于Python是動態(tài)語言,根據(jù)類創(chuàng)建的實例可以任意綁定屬性。
給實例綁定屬性的方法是通過實例變量,或者通過self變量:
class Student(object):def __init__(self, name):self.name = names = Student('Bob') s.score = 90?但是,如果Student類本身需要綁定一個屬性呢?可以直接在class中定義屬性,這種屬性是類屬性,歸Student類所有:
class Student(object):name = 'Student'?當(dāng)我們定義了一個類屬性后,這個屬性雖然歸類所有,但類的所有實例都可以訪問到。來測試一下:
>>> class Student(object): ... name = 'Student' ... >>> s = Student() # 創(chuàng)建實例s >>> print(s.name) # 打印name屬性,因為實例并沒有name屬性,所以會繼續(xù)查找class的name屬性 Student >>> print(Student.name) # 打印類的name屬性 Student >>> s.name = 'Michael' # 給實例綁定name屬性 >>> print(s.name) # 由于實例屬性優(yōu)先級比類屬性高,因此,它會屏蔽掉類的name屬性 Michael >>> print(Student.name) # 但是類屬性并未消失,用Student.name仍然可以訪問 Student >>> del s.name # 如果刪除實例的name屬性 >>> print(s.name) # 再次調(diào)用s.name,由于實例的name屬性沒有找到,類的name屬性就顯示出來了 Student?從上面的例子可以看出,在編寫程序的時候,千萬不要對實例屬性和類屬性使用相同的名字,因為相同名稱的實例屬性將屏蔽掉類屬性,但是當(dāng)你刪除實例屬性后,再使用相同的名稱,訪問到的將是類屬性。
總結(jié)
以上是生活随笔為你收集整理的python 面向对象编程:类和实例的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python生成器generator:深
- 下一篇: pandas:数据规范化方法与pytho