[TOC]
<br>
### 類與實例的定義
>[info] 我們描述人類,動物時,很顯然他們是不同的類,具有不同的特性,我們將具有相同特性的一類事務劃到一個`類`型中。
而張三、李四,王五是人類中的一個具體的實例對象,他們具有人類的所有特性,但是他們又是不同的`實例`,例如他們的能力,外貌等各不相同。
類(Class)是面向對象程序設計(OOP,Object-Oriented Programming)實現信息封裝的基礎。**類是一種用戶定義類型,也稱類類型**。每個類包含數據說明和一組操作數據或傳遞消息的函數。類的實例稱為對象。
類的構成包括**數據成員**和**成員函數**,數據成員對應類的屬性,成員函數則用于操作類的各項屬性,是一個類具有的特有的操作。
### python中的類與實例
類的定義:
```python
class Person(object):
""" 定義一個人類
人類具有屬性:性別
人類具有行為能力:說話
"""
sex = "boy" # 類屬性
def __init__(self, name):
""" 構造方法,在創建類實例時,初始化作用"""
self.name = name # 實例屬性
def say_hello(self, language): # 實例方法
""" 自定義方法"""
result = {"name": self.name, "sex": self.sex, "language": language}
return result
```
類的使用:
```python
# 創建實例對象(一只具體的人),傳入構造方法中規定的參數,初始化這個人的name屬性值為sandy
p1 = Person("sandy")
print("p1:", p1) # 輸出對象
print(p1.say_hello("普通話")) # 實例對象用'.'來調用類中的普通自定義方法
print("p1.sex:", p1.sex) # 實例對象用'.'來調用類中的普通屬性
```
運行結果:
```cmd
p1: <__main__.Person object at 0x0000000000BED240>
{'name': 'sandy', 'language': '普通話', 'sex': 'boy'}
p1.sex: boy
```
***代碼解釋:***
這個實例,是最常用的一種類結構了。
1. 在python中,通過**關鍵字`class` 來聲明類**,class后面跟著類名,這里定義了類"Person",類名后面的括號里面跟著該類的父類,這里的“object”是所有類的基類,這是一種新式類的寫法,經典類中可以沒有。建議都使用形式類吧,經典類就不提了。
2. 類中的方法,與之前學習的函數是否感覺特別相似?但是在類中,它叫方法,它的第一個參數固定是`self`,它表示**實例對象自身**,通過self.XXX 可以調用實例對象所擁有的屬性和方法。
3. **實例,是通過類來創造的**。實例被創建后,就擁有了操作類屬性和類方法的功能。
將類實例化,在java中需要`new`出來,而在python中,`類名([初始化參數])`就可以實例出一個對象了。創建實例時,首先就調用類中的構造方法\__init__,在\__init__中初始化一些需要外部傳入的參數值給類屬性。
### 屬性
#### 類屬性
是在聲明類后,就存在與內存中,能夠通過類來直接訪問,如Person.sex
#### 實例屬性
則只有在實例化后才會存在,如果直接通過類訪問,如Person.name 則會報錯:AttributeError: type object 'Person' has no attribute 'name'
#### 私有屬性
在python中,有一種私有屬性,命名時,以兩個下劃線開頭,如下:
```python
class Person(object):
""" 定義一個人類
人類具有屬性:性別
人類具有行為能力:說話
"""
sex = "boy" # 類屬性
def __init__(self, name):
""" 構造方法,在創建類實例時,初始化作用"""
self.name = name
self.__age = 100 # 設置私有屬性
def say_hello(self, language): # 自定義類方法
""" 自定義方法"""
result = {"name": self.name, "sex": self.sex, "language": language}
return result
def get_age(self):
return self.__age
```
編譯的時候,私有屬性__age自動加上類名,變成`_Person__membername`,這種技術叫變量名壓縮(mangling),以達到外部不能調用的目的
**創建實例p1**
```cmd
p1 = Person('Sandy')
```
**調用私有屬性__age:**
如果直接通過實例調用__age,如 p1.__age,則會報錯:AttributeError: 'Person' object has no attribute '__age'
但是可以通過以下兩種方式訪問到__age,如
p1.get_age()
p1._Person__age
對于私有屬性,我們一般都會通過第一種封裝函數來訪問。
### 方法
1. 方法是類內部定義的函數(意味著方法是類屬性而不是實例屬性)
2. ***方法只有在所屬的類擁有實例時,才能被調用***,當存在一個實例時,方法才被認為是綁定到那個實例了
3. 任何一個方法定義中的第一個參數都是變量`self`,它表示調用此方法的實例對象。對于已綁定的方法調用來說,self是自動傳遞給這個方法的,在調用的時候就不需要傳入這個參數了。
#### 靜態方法@staticmethod與類方法@classmethod
>由前面的介紹可知,類中的方法,第一個參數都是self.
類中定義的方法,需要實例化后才能調用。
能否實現在方法中,不需要傳入self,不需要實例化,直接通過類就能調用?
在python中,可以通過聲明`靜態方法`和`類方法`來實現。
**靜態方法**:在類方法中,存在與類相關,但是又不需要改變類和實例狀態的方法,這類方法可以聲明為靜態方法,靜態方法不需要訪問類里的任何參數。所帶的參數都是從外部傳入的。使用函數修飾符 @staticmethod 將方法聲明為靜態方法。
**類方法**:
python中使用函數修飾符@classmethod 將方法聲明為類方法,可以被類直接調用。
類方法第一個參數必須是類屬性,一般用cls,因此我們可以在方法里面調用類的屬性、方法
```python
class Person(object):
""" 定義一個人類
人類具有屬性:性別
人類具有行為能力:說話
"""
sex = "boy" # 類屬性
def __init__(self, name):
""" 構造方法,在創建類實例時,初始化作用"""
self.name = name
def say_hello(self, language): # 類方法
""" 自定義方法"""
result = {"name": self.name, "sex": self.sex, "language": language}
return result
@staticmethod
def sing(song):
print("sing:", song)
@classmethod
def run(cls, distance):
print("run:", distance,"sex:",cls.sex)
```
調用方式:
```python
Person.sing("HIJKLMN...") # 類直接調用靜態方法
Person.run("400") # 類直接調用類方法
Sandy=Person('Sandy')
Sandy.sing("ABCDEFG...") # 通過實例調用靜態方法
Sandy.run("8000") # 通過實例調用類方法
```
運行結果:
```cmd
sing: HIJKLMN...
run: 400 sex: boy
sing: ABCDEFG...
run: 8000 sex: boy
```
#### 屬性方法 @property
@property`把一個函數變成一個靜態屬性,直接調用函數名字`,不需要加括號,就能獲取到函數返回值。一般用在不注重過程,只要結果的情況!
```python
class Person(object):
""" 定義一個人類
"""
sex = "boy" # 類屬性
def __init__(self, name):
""" 構造方法,在創建類實例時,初始化作用"""
self.name = name
self.__age = 100
@property
def age(self):
return self.__age
Sandy = Person('Sandy')
print(Sandy.age) #不需要括號,看起來完全是一個屬性,這就是屬性方法
```
運行結果:
```cmd
100
```
### 類中內置的幾個特殊方法
#### \__new__,\__init__,\__del__,\__str__
通過實例,了解他們的調用時機
```python
class Person(object):
""" 定義一個人類
"""
def __init__(self,name):
self.name=name
print("__init__ function call")
def __new__(cls, *args, **kwargs):
print("__new__ function call")
return super(Person, cls).__new__(cls)
def __del__(self):
print("__del__ function call")
def __str__(self):
print("__str__ function call")
return self.name
print("*"*30)
Sandy = Person('Sandy')
print("*"*30)
print(Sandy)
print("*"*30)
del Sandy
```
運行結果如:
```cmd
******************************
__new__ function call
__init__ function call
******************************
__str__ function call
Sandy
******************************
__del__ function call
```
\__new__() 是在新式類中新出現的方法,它作用在構造方法創建實例之前
\__init__() 構造方法,它作用于創建實例之時
\__str__() 作用于輸出實例對象時
\__del__() 作用于銷毀實例對象時
### 類的繼承
在python中,object是新式類最頂級的類,是所有類的基類。
在前面的舉例中,Person是人`類`,那么,“中國人”,“美國人”,“法國人”等也是`人類`中劃分更細的一個群體,也可以定義成一個類,并且這些類具有`人類`的一切特征,但是又有屬于自己特有的特征。
我們定義“中國人”,“美國人”類時,直接**繼承**人類,即可實現在“中國人”和“美國人”這些`子類`中,無需重復編寫相同的特性與屬性,可以直接使用`父類`Person中定義的屬性和方法。
#### 成員屬性和方法的繼承
```python
class Person(object):
""" 定義一個人類"""
sex = "Boy"
def say_hello(self, language): # 類方法
""" 自定義方法"""
print("Lanuage:", language)
class Chiness(Person):
""" 定義中國人 類"""
nature = "Love Peace!"
p1 = Chiness()
print(p1.sex) # 從子類中,可以調用父類的成員數據
p1.say_hello("普通話") # 從子類中,可以調用父類的方法
```
運行結果:
```cmd
Boy
Lanuage: 普通話
```
#### 子類對父類方法的重寫
子類的的方法如果和父類的方法重名,子類會覆蓋掉父類。
```python
class Person(object):
""" 定義一個人類"""
sex = "Boy"
def say_hello(self, language): # 類方法
""" 自定義方法"""
print("Lanuage:", language)
class Chiness(Person):
""" 定義中國人 類"""
nature = "Love Peace!"
def say_hello(self,language):
print("您好,我是中國人,我的母語是",language)
p1 = Chiness()
p1.say_hello("普通話") # 從子類中,調用父類的方法
```
在Chiness類中,具有與父類方法名相同的say_hello,當Chiness的實例對象調用say_hello時,就會使用Chiness中的say_hello。
運行結果:
```cmd
您好,我是中國人,我的母語是 普通話
```
#### 構造方法的繼承與重寫
一般來說,子類的構造方法都是先繼承,然后擴展。其中,
**新式類**的構造方法繼承寫法如:***`supper(子類,self).__init__(參數1,參數2...)`***
**經典類**的構造方法繼承寫法如:*父類名稱.\__init__(self,參數1,參數2,...)*
```python
class Person(object):
""" 定義一個人類"""
sex = "Boy"
def __init__(self, name):
self.name = name
def say_hello(self): # 類方法
""" 自定義方法"""
print("name:", self.name)
class Chiness(Person):
""" 定義中國人 類"""
def __init__(self, name, nature):
super(Chiness, self).__init__(name) # 先繼承父類的構造方法
self.nature = nature # 擴展子類的構造方法
def say_hello(self):
print("您好,我是中國人,我的名字是【{name}】,我的天性是【{nature}】".format(name=self.name, nature=self.nature))
p1 = Chiness("張三", "愛好和平")
p1.say_hello()
```
運行結果:
```cmd
您好,我是中國人,我的名字是【張三】,我的天性是【愛好和平】
```
### 多態
>子類的的方法如果和父類的方法重名,子類會覆蓋掉父類。因為這個特性,就獲得了一個繼承的好處”多態”。
```python
class Person(object):
""" 定義一個人類"""
def __init__(self, name):
self.name = name
def say_hello(self): # 類方法
""" 自定義方法"""
print("name:", self.name)
class Chiness(Person):
""" 定義中國人 類"""
def __init__(self, name, nature):
super(Chiness, self).__init__(name) # 先繼承父類的構造方法
self.nature = nature # 擴展子類的構造方法
def say_hello(self):
print("您好,我是中國人,我的名字是【{name}】,我的天性是【{nature}】".format(name=self.name, nature=self.nature))
class America(Person):
""" 定義一個美國人 類"""
def __init__(self, name, nature):
super(America, self).__init__(name) # 先繼承父類的構造方法
self.nature = nature # 擴展子類的構造方法
def say_hello(self):
print("Hello,I am America,My name is 【{name}】,my nature is 【{nature}】".format(name=self.name, nature=self.nature))
def say_hello(people):
people.say_hello()
p1 = Chiness("張三", "愛好和平")
p2 = America("Perter","fighting")
# 同一個方法,傳入不同的人,會說出不同的問候,這便是一種多態...
say_hello(p1)
say_hello(p2)
```
運行結果:
```cmd
您好,我是中國人,我的名字是【張三】,我的天性是【愛好和平】
Hello,I am America,My name is 【Perter】,my nature is 【fighting】
```
<hr style="margin-top:100px">
:-: 
***微信掃一掃,關注“python測試開發圈”,了解更多測試教程!***
- 前言
- chapter01_開發環境
- chapter02_字符串的使用
- chapter03_列表的使用
- chapter04_字典的使用
- chapter05_數字的使用
- chapter06_元組的使用
- chapter07_集合的使用
- chapter08_輸入輸出
- chapter09_控制流程
- chapter10_實例練習_登錄1
- chapter11_python函數入門
- chapter12_python中的類
- chapter13_輕松玩轉python中的模塊管理
- chapter14_掌握學習新模塊的技巧
- chapter15_通過os模塊與操作系統交互
- chapter16_子進程相關模塊(subprocess)
- chapter17_時間相關模塊(time & datetime)
- chapter18_序列化模塊(json)
- chapter19_加密模塊(hashlib)
- chapter20_文件的讀與寫
- chapter21_階段考核2_登錄
- chapter22_小小算法挑戰(排序&二分法)
- chapter23_用多線程來搞事!
- chapter24_HTTP接口請求(requests)
- chapter25_接口測試框架(pytest)
- chapter26_階段考核3_HTTP接口測試
- chapter27_HTML解析(pyquery)
- chapter28_階段考核4_爬蟲下載網易汽車
- chapter29_python中的那些編碼坑
- chapter30_MySQL數據庫操作
- chapter31 高級特性_迭代器與生成器
- chapter32 高級特性_裝飾器
- chapter33 高級特性_列表處理