菜鳥學python之類和對象
我們把一類相同的事物叫做類,其中相同事物相同的屬性可以抽象出來,而一些相同的動作行為,也可以抽象成方法。
比如,汽車是一個類,它包括價格、品牌等屬性。那麽我們需要打印某一輛車的價格和品牌,只需要使用一句代碼 print "the car‘s type ‘ford’,price:280000",但是當我們需要對一百個品種的車打印這句話的時候,怎麽辦呢?
這個問題我們通過以前學過的函數式編程就可以實現啦!我們只需要寫一個類,然後將不同的車品牌和價格以參數的方式傳到類裏就好了。這樣大大的提高了代碼的重用性,我們就不需要把同樣的print這句話寫100次了。
class Car: def __init__(self,type,price): self.type=type self.price=price def printInfo(self): print(‘the car‘+self.type+‘\‘s price is:‘+str(self.price)) carOne=Car(‘passat‘,25000) carTwo=Car(‘ford‘,25000000) carOne.printInfo() carTwo.printInfo() the carpassat‘s price is:25000 the carford‘s price is:25000000
想一想,如果沒有這些做法,想要打印信息,那會多麻煩?而創建好類模版後,我們只需要根據具體情況創建不同對象(實例),然後再調用對象內的封裝好的打印函數就好
1.self是個什麽鬼
self是自身對象的引用,也是一個變量。創建不同對象時,self自然指向的對象也就不同;
所以當我們使用passat這個對象去調用printCarInfo這個方法的時候,其實是做了這樣一部操作printCarInfo(passat),把passat這個對象傳給了printCarInfo方法,passat這個對象又包含了兩個屬性cartype、price,我們在python規定這樣使用一個對象中的變量:passat.cartype、passat.price
在對象中,屬性有點類似一個家庭中的物件,而方法相當於是要使用物件的人,人和物件都屬於這個家庭,但是不給人指定具體哪個物件,人還可以使用人家的東西,萬一借來的呢?所以要指定使用自己家的,就要用一個self(指向自家家庭的門牌號)
類的初始化過程:
carOne=Car(‘passat‘,25000)
其實這兩句話每句話都完成了三個功能:
第一,從car類中實例化出了一個對象——passat/ford;
第二:給新對象的屬性賦了值
第三:將引用調給carOne
2 init 初始化函數
由於類可以起到模板的作用,因此,可以在創建實例的時候,把一些我們認為必須綁定的屬性強制填寫進去。通過定義一個特殊的 __init__ 方法,在創建實例的時候,就把 type ,price等屬性綁上去:
註意到 __init__ 方法的第一個參數永遠是 self ,表示創建的實例本身,因此,在 __init__ 方法內部,就可以把各種屬性綁定到 self ,因為 self就指向創建的實例本身。有了 __init__ 方法,在創建實例的時候,就不能傳入空的參數了,必須傳入與 __init__ 方法匹配的參數,但 self 不需要傳,Python 解釋器自己會把實例變量傳進去
3 方法
我們在使用printInfo函數打印數據時,不需要到外部去執行。直接封裝在內部。這樣,就把“數據”給封裝起來了。這些封裝數據的函數是和Car類本身是關聯起來的,我們稱之為類的方法
要定義一個方法,除了第一個參數是 self 外,其他和普通函數一樣。要調用一個方法,只需要在實例變量上直接調用,除了 self 不用傳遞,其他參數正常傳入
def printInfo(self): print(‘the car‘+self.type+‘\‘s price is:‘+str(self.price)) carOne.printInfo()
這樣一來,我們從外部看 Car 類,就只需要知道,創建實例需要給出 type 和 price ,而如何打印,都是在 Student 類的內部定義的,這些數據和邏輯被“封裝”起來了,調用很容易,但卻不用知道內部實現的細節。
4 訪問限制
從前面 Student 類的定義來看,外部代碼還是可以自由地修改一個實例的 price 、 type 屬性:
carOne.price=250 the carpassat‘s price is:250
1)私有屬性
如果要讓內部屬性不被外部訪問,可以把屬性的名稱前加上兩個下劃線__ ,在 Python 中,實例的變量名如果以 __ 開頭,就變成了一個私有變量(private),只有內部可以訪問,外部不能訪問
class Car: def __init__(self,type,price): self.__type=type self.__price=price carOne=Car(‘wote‘,20) carOne.price AttributeError: ‘tuple‘ object has no attribute ‘price‘
此時已經不能訪問了,如果想訪問咋辦?
通過內部方法返回值
如果想改變咋辦?
def get_price(self) return self.__price def get_type(self) return self.__type
通過內部方法傳入值,再賦值給self
def set_price(self,price) self.__price=price def set_type(self,type) self.__type=type
思考:
原先那種直接通過 carOne.price = 2500 也可以修改啊,為什麽要定義一個方法大費周折?
因為在方法中,可以對參數做檢查,避免傳入無效的參數:
def set_price(self,price) if 0<=price<=3000: self.__price=price else: print(‘i cant pay‘)
雙下劃線開頭的實例變量是不是一定不能從外部訪問呢?其實也不是。不能直接訪問 __price 是因為 Python 解釋器對外把 __price 變量改成了_Car__price ,所以,仍然可以通過 _Car__price 來訪問 __price 變量,但最好別這樣幹
實例屬性和類屬性
由於 Python 是動態語言,根據類創建的實例可以任意綁定屬性。給實例綁定屬性的方法是通過實例變量,或者通過 self 變量:
class Student: def __init__(self, name): self.name = name s = Student(‘Bob‘) s.score = 90
但是,如果 Student 類本身需要綁定一個屬性呢?可以直接在 class 中定義屬性,這種屬性是類屬性,歸 Student 類所有:
class Student: name = ‘Student‘
當我們定義了一個類屬性後,這個屬性雖然歸類所有,但類的所有實例都可以訪問到。來測試一下:
>>> class Student(object): ... name = ‘Student‘ ... >>> s = Student() # 創建實例 s >>> print(s.name) # Student >>> print(Student.name) # 打印類的 name 屬性 Student >>> s.name = ‘Michael‘ # 給實例綁定 name 屬性 >>> print(s.name) # 由於實例屬性優先級比類屬性高,因此,它會屏蔽掉類的name 屬性 Michael >>> print(Student.name) # 但是類屬性並未消失,用 Student.name 仍然可以訪問 Student >>> del s.name # 如果刪除實例的 name 屬性 >>> print(s.name) # 再次調用 s.name,由於實例的 name 屬性沒有找到,類的name 屬性就顯示 Student
從上面的例子可以看出,在編寫程序的時候,千萬不要把實例屬性和類屬性使用相同的名字,因為相同名稱的實例屬性將屏蔽掉類屬性,但是當你刪除實例屬性後,再使用相同的名稱,訪問到的將是類屬性。
本文出自 “11818322” 博客,請務必保留此出處http://11828322.blog.51cto.com/11818322/1967264
菜鳥學python之類和對象