1. 程式人生 > >python之路-day16-類的成員

python之路-day16-類的成員

一、昨日內容回顧
1、面向物件與面向過程
面向過程:以我為中心。按照事物發展的流程順序來寫程式碼
優點:程式碼量少,簡單
缺點:擴充套件性差

面向物件:以物件為中心,所有的東西都是獨享。操縱的是物件,讓獨享去完成相應的操作

2、物件是通過類來建立的
類是屬性和方法的結合體,歸類某一個事物,我們寫的每一個類都是一個數據型別

class 類(父類):
def __init__(self) : 構造方法。在建立物件的時候自動呼叫
pass

def 方法(self):
pass

a = 類() # 這裡呼叫的是__init__()

# 訪問物件 a 的屬性
a.屬性
# 方法
a.方法()
self: 類的物件

總結:

大專案用面向物件;小指令碼用面向過程

3、面向物件的三大特性
封裝:
1、對屬性的封裝
2、對方法的封裝
繼承:
子類可以自動擁有父類中除了私有內容外的所有內容
多型:
同一個物件擁有多種形態。鴨子模型

二、類的成員
首先,什麼是類的成員?在類中書寫什麼?寫的內容就是成員。

class 類名:
# 方法
def __init__(self,引數1,引數2...):

# 屬性變數
self.屬性1 = 引數1
self.屬性2 = 引數2
...
# 方法
def method(self):
pass
在上述程式碼中 __init__ 和 method都屬於類的成員方法。又稱為例項方法。總之這樣的
東西需要用物件來訪問。而上面的self.屬性1 = 引數1 這個程式碼的含義是給物件設定屬性資訊
含義是這個物件的xxx屬性是xxxx. 這種東西有被稱之為成員變數或者例項變數。

三、類的成員 - 變數

在類中變數分成兩大類:

1、例項變數(欄位)
2、類變數(靜態變數)

先說什麼是例項變數。說白了,就是每個例項都應該擁有的變數。比如:人的名字,人的愛好,每個人
的個人資訊。都屬於例項變數。那什麼是類變數。就是這一類事物統一擁有的變數。比如:大家都是中國
人。

class Person:
#類變數,表示所有的該類的物件都共享這個變數
country = "中國"

def __init__(self, name , num , birthday):
# 例項變數(欄位) 表示你建立的每一個人都有這三個變數
self.name = name
self.num = num
self.birthday = birthday
p1 = Person("alex", 18 , "1980")
print(p1.name) # alex
print(p1.country) # 中國

p2 = Person("wusir", 28 , "1982")
print(p2.name) # wusir
print(p2.country) # 中國

我們發現p1 和 p2 的name都是物件自己的。但是country是類的,大家共有一個變數

Person.country = "華夏" # 在這裡我們把國家改成了 華夏
p1 = Person("alex", 18 ,"1980")
print(p1.name)
print(p1.country) # alex 是華夏的

p2 = Person("wusir" , 28 , "1982")
print(p2.name)
print(p2.country) # wusir 也是華夏的

從上我們可以發現類變數中的值改變了。所有物件中的該屬性也跟著改變(前提是物件屬性中無該屬性)

 

            

 

通過圖我們能發現,例項變數中都隱含著一個建立這個物件的類。通過類就能找到我們類中定義的全部
內容,包括方法和屬性資訊等
接下來,我們來看一個和類變數嘻嘻相關的坑

p1 = Person("alex", 18 , "1980")
p1.country = "華夏"
print(p1.name)
print(p1.country) # 華夏

p2 = Person("wusir", 28 , "1982")
print(p2.name)
print(p2.country) # 中國

上面是 華夏,下面是中國? p1.country = "華夏"的時候,氣死並沒有去改變類中的country,
而是給獨享添加了一個例項變數。並且這個例項變數,只有在當前的p1是存在的。在p2中是不存在的。

在圖中,我們能清晰的看到,p1.country = "華夏" 並沒有改變類變數,只是p1中添加了一個例項
變數,僅此而已。通過這裡,我們應該能發現,類變數,最好是用類名來訪問。當然,我們通過物件名也
可以訪問。單隻能看,不能改變它。想要改變它,需要用類名來改變它。

案例: 通過程式記錄當前類被建立了多少個物件

class Foo:
count = 0
def __init__(self):
Foo.count += 1
print(Foo.count) # 0
Foo()
Foo()
Foo()
print(Foo.count) # 3

好了,來做個簡單的總結:
例項變數,給物件用的
類變數,多個物件共享的。最好是用類名來訪問。這樣更加規範


四、類的成員-方法
1、成員方法(例項方法)
2、靜態方法
3、類方法

1、成員方法 -- 物件直接訪問的方法叫做成員方法

class Computer:

# 成員方法(例項方法)
def play(self):
print("我的電腦可以玩")

c = Computer()
c.play() # 物件直接去呼叫成員方法(例項方法)

2、靜態方法。靜態方法不需要我們給方法傳遞 self。也就是說,當出現一個方法不需要使用到成員變數的
時候,就可以選擇使用靜態方法。靜態方法需要我們在方法上面新增一個裝飾器 @staticmethod

@staticmethod
def fare():
print("我的電腦非常牛逼,可以煎雞蛋")

靜態方法和靜態變數一樣,一般都是使用類名直接訪問和呼叫的

Computer.fare() # 類名可以直接訪問的
c.fare() # 物件也可以直接訪問,但最好不要這麼幹,以便區分靜態方法和例項方法

3、類方法
類方法,類方法和靜態方法差不多,只不過類方法需要在引數列表中的第一個位置預留一個位置,通常
我們給第一個引數起名字叫 cls,類方法在被呼叫的時候也不需要傳遞例項物件。但是,系統會自動把類
傳遞給第一個引數。類方法在編寫的時候,需要在類方法上面新增 @classmethod

class Computer:

def play(self):
print("我的電腦可以玩")

@staticmethod
def fare():
print("我的電腦非常牛逼,可以煎雞蛋")

@classmethod
def cal(cls, a, b):
print(cls)
return a+b
print(Computer.cal(1,2)) # 此時會自動芭蕾名傳遞給類方法的第一個引數


4、思考 類方法/靜態方法和例項方法有什麼區別?

例項方法:
定義:第一個引數必須是例項物件,該參名一般約定為"self",通過它來傳遞例項的屬性和方法(也可傳
類的屬性和方法);
呼叫:
只能由例項物件呼叫

類方法:
定義:使用裝飾器 @classmethod。第一個引數必須是當前類的物件,該引數名一般約定為"cls",通過
它來傳遞類的屬性和方法(不能傳例項的屬性和方法);
呼叫: 例項物件和類物件都可以呼叫

靜態方法
定義: 使用裝飾器@staticmethod,引數隨意,沒有"self"和"cls"引數,方法中不能使用類和例項的
任何屬性和方法;
呼叫:例項物件和類物件都可以呼叫


五、 類的成員-屬性

屬性其實就是通過方法改造過來的一種變數的寫法,在方法上新增一個 @property就可以了

class Person:
def __init__(self):
pass

@property
def age(self):
return 1

p = Person()
age = p.age

print(age)

應用場景:我們一般儲存資料的時候,不會儲存一個人的年齡。因為隨著時間的推移,每個人
的年齡都時刻在改變著。那麼如何儲存更加完美呢? 其實只需儲存出生年月日。然後用程式來計算;
而計算屬於一個功能。當然要寫進方法裡了,但是對於年齡這個屬性而言,他應當是一個數值。而
不是動作。所以python就提供了這樣的一種機制。通過方法來描述一個屬性。
注意:
1、方法引數只能有一個self
2、方法上方要寫@property
3、呼叫的時候,我們不需要寫括號。直接當成屬性變數來用就可以了。
4、這種套路只能取值,不能設定值

六、私有

在python中,一般是不提倡設定和使用私有資訊的。但是有些場景,我們不得不這樣做。比如,
在一家公司,每個人的收入情況,這種內容是絕對不能公開的。
在python中,使用 __ 作為方法或者變數的字首。name這個方法或者變數就是私有的

1、私有變數
class Person:
def __init__(self, laopo, mimi):
self.__laopo = laopo # 私有的
self.__mimi = mimi
alex = Person("wusir", "他倆搞基")
print(alex.__mimi) # 私有的. 誰都不能碰

程式報錯. 私有的內容是訪問不到的. 但是, 這個訪問不到是有⼀定的侷限性的. 比如:

class Person:
def __init__(self, laopo, mimi):
self.__laopo = laopo # 私有的
self.__mimi = mimi
def gaosuni(self):
print("⼤喇叭開始⼴播了")
return self.__mimi # 私有的內容.在他⾃⼰那⾥, 他可以任意的進⾏使⽤
alex = Person("wusir", "他倆搞基")
mimi = alex.gaosuni() # 通過⼀個⾮私有的⽅法, 訪問到了他的祕密.
print(mimi)

記住,私有的內容不能直接訪問,但是如果對方開闢了外界訪問的通道(公共方法),那可以通過這個
公共方法來獲取到私有內容。這樣做的好處是:外界只能看,但是改不了

不單單例項變數有私有的。類變數(靜態變數) 一樣擁有這樣的屬性:
class Person:
__zisi = "⼈都是⾃私的" # ⼈都是⾃私的. 但是這個⾃私⼜不希望別⼈知道
def __init__(self, laopo, mimi):
self.__laopo = laopo # 私有的
self.__mimi = mimi
def gaosuni(self):
print("⼤喇叭開始⼴播了")
return self.__mimi
alex = Person("wusir", "他倆搞基")
mimi = alex.gaosuni()
print(mimi)
print(Person.__zisi) # 報錯

2、私有方法

私有方法,顧名思義,只能自己訪問的方法,別人都不能隨便呼叫的。
class Person:
def __init__(self):
pass
def __yue(self):
print("我要約會")
def job(self):
print("我要⼯作")
p = Person()
# p.__yue() # 報錯
p.job()
__yue是一個私有的方法,只能在類中自己呼叫,類外面不能訪問
job是一個成員方法,並且是一個開放的方法,在類外界可以被訪問到

注意:私有的內容子類是無法繼承的