Python Class物件導向(一)

用書 PYTHON王者歸來 作者洪錦魁

Class 定義和使用

class Nini():
    classname = "mathA"
    def motto(number):
        return "00122"
NINIinfo = Nini()
print(NINIinfo.classname)
print(NINIinfo.motto())

執行結果

class Nini():
    classname = "mathA"
    def __init__(self,username,number):
        self.name = username
        self.num = number
    def get_num(self):
        return self.num
NINIinfo = Nini("Ni",10012)

print(NINIinfo.name.title(),NINIinfo.get_num())

class Bank():
    Bankname = "Tokyostar"
    def __init__(self,username,money):
        self.name = username
        self.totalmoney = money
    def save_money(self, money):
        self.totalmoney += money
        print("save money",money)
    def withdraw_money(self, money):
        self.totalmoney -= money
        print("withdraw money",money)
    def ge_totalmoney(self):
        print(self.name.title(),"Currently money:",self.totalmoney)

mybank = Bank("Nini",10000)
mybank.ge_totalmoney()
mybank.save_money(1000)
mybank.ge_totalmoney()
mybank.withdraw_money(50)
mybank.ge_totalmoney()

執行結果

class Bank():
    Bankname = "Tokyostar"
    def __init__(self,username,money):
        self.name = username
        self.totalmoney = money
    def save_money(self, money):
        self.totalmoney += money
        print("save money",money)
    def withdraw_money(self, money):
        self.totalmoney -= money
        print("withdraw money",money)
    def ge_totalmoney(self):
        print(self.name.title(),"Currently money:",self.totalmoney)

Ninibank = Bank("Nini",10000)
Papabank = Bank("Papa",20000)
Ninibank.ge_totalmoney()
Papabank.ge_totalmoney()
Ninibank.save_money(1000)
Ninibank.withdraw_money(1000)
Papabank.save_money(5000)
Papabank.withdraw_money(50)
Ninibank.ge_totalmoney()
Papabank.ge_totalmoney()

執行結果

class Bank():
    
    def __init__(self,username):
        self.name = username
        self.totalmoney = 0
        self.bankname = "Tokyostar"

    def save_money(self, money):
        self.totalmoney += money
        print("save money",money)

    def withdraw_money(self, money):
        self.totalmoney -= money
        print("withdraw money",money)

    def ge_totalmoney(self):
        print(self.name.title(),"Currently money:",self.totalmoney)

Ninibank = Bank("Nini")
Papabank = Bank("Papa")
print("Ninibank bank is:", Ninibank.bankname)
print("papabank bank is:", Papabank.bankname)
Ninibank.ge_totalmoney()
Papabank.ge_totalmoney()
Ninibank.save_money(1000)
Ninibank.withdraw_money(1000)
Papabank.save_money(5000)
Papabank.withdraw_money(50)
Ninibank.ge_totalmoney()
Papabank.ge_totalmoney()

執行結果

封裝(encapsulation)

私有屬性

為了不讓外部直接存取露別的屬性,要在PYTHON的內部增加私有屬性(private attribute)

宣告時在屬性名稱前增加兩個底線 __私有屬性後,類別外的程式就無法引用了

外部直接存取屬性質(不安全)

class Bank():

    def __init__(self,username):
        self.name = username
        self.totalmoney = 0
        self.bankname = "Tokyostar"

    def save_money(self, money):
        self.totalmoney += money
        print("save money",money)

    def withdraw_money(self, money):
        self.totalmoney -= money
        print("withdraw money",money)

    def ge_totalmoney(self):
        print(self.name.title(),"Currently money:",self.totalmoney)

Ninibank = Bank("Nini")
Ninibank.ge_totalmoney()
Ninibank.totalmoney =150
Ninibank.ge_totalmoney()

執行結果

宣告 私有屬性 增加兩個底線 __

class Bank():

    def __init__(self,username):
        self.__name = username
        self.__totalmoney = 0
        self.__bankname = "Tokyostar"

    def save_money(self, money):
        self.__totalmoney += money
        print("save money",money)

    def withdraw_money(self, money):
        self.__totalmoney -= money
        print("withdraw money",money)

    def ge_totalmoney(self):
        print(self.__name.title(),"Currently money:",self.__totalmoney)

Ninibank = Bank("Nini")
Ninibank.ge_totalmoney()
Ninibank.__totalmoney =150
Ninibank.ge_totalmoney()

執行結果

破解私有屬性

物件名稱. _類別名稱 __ __ 私有屬性 Ninibank._Bank__totalmoney =150

class Bank():

    def __init__(self,username):
        self.__name = username
        self.__totalmoney = 0
        self.__bankname = "Tokyostar"

    def save_money(self, money):
        self.__totalmoney += money
        print("save money",money)

    def withdraw_money(self, money):
        self.__totalmoney -= money
        print("withdraw money",money)

    def ge_totalmoney(self):
        print(self.__name.title(),"Currently money:",self.__totalmoney)

Ninibank = Bank("Nini")
Ninibank.ge_totalmoney()
Ninibank.__totalmoney =150
Ninibank.ge_totalmoney()
Ninibank._Bank__totalmoney =150
Ninibank.ge_totalmoney()

執行結果

私有方法

class Bank():

    def __init__(self,username):
        self.__name = username
        self.__totalmoney = 0
        self.__bankname = "Tokyostar"
        self.__rate = 0.22
        self.__service_charge = 0.01

    def save_money(self, money):
        self.__totalmoney += money
        print("save money",money)

    def withdraw_money(self, money):
        self.__totalmoney -= money
        print("withdraw money",money)

    def ge_totalmoney(self):
        print(self.__name.title(),"Currently money:",self.__totalmoney)
    
    def jp_to_taiwan(self,jp):
        self.result = self.__cal_rate(jp)
        return self.result
    
    def __cal_rate(self,jp):
        return int(jp*self.__rate*(1-self.__service_charge))

Ninibank = Bank("Nini")
JP_en = 100
print("jp:",JP_en,"TW:",Ninibank.jp_to_taiwan(JP_en))

執行結果

破解私有方法

直接呼叫私有屬性會發生錯誤



Ninibank.__cal_rate(0.29)

執行結果

class Bank():

    def __init__(self,username):
        self.__name = username
        self.__totalmoney = 0
        self.__bankname = "Tokyostar"
        self.__rate = 0.22
        self.__service_charge = 0.01

    def save_money(self, money):
        self.__totalmoney += money
        print("save money",money)

    def withdraw_money(self, money):
        self.__totalmoney -= money
        print("withdraw money",money)

    def ge_totalmoney(self):
        print(self.__name.title(),"Currently money:",self.__totalmoney)
    
    def jp_to_taiwan(self,jp):
        self.result = self.__cal_rate(jp)
        return self.result
    
    def __cal_rate(self,jp):
        return int(jp*self.__rate*(1-self.__service_charge))

Ninibank = Bank("Nini")
# JP_en = 180
# print("jp:",JP_en,"TW:",Ninibank.jp_to_taiwan(JP_en))
print(Ninibank._Bank__cal_rate(180))

執行結果

property()

從外部可以修改數字

class mymoney():
    def __init__(self,money):
        self.money = money
Ninimoney = mymoney(100)
print(Ninimoney.money)
Ninimoney.money =60
print(Ninimoney.money)

執行結果

將mymoney設為私有屬性

class mymoney():
    def __init__(self,money):
        self.__money = money
    def getmoney(self):
        print("inside the getmoney")
        return self.__money
    def setmoney(self,money):
        print("inside the setmoney")
        self.__money = money

Ninimoney = mymoney(100)
print(Ninimoney.getmoney())
Ninimoney.setmoney(80)
print(Ninimoney.getmoney())

執行結果

無法重外部強制修改

執行結果

新式PYTHON風格  property(getter[,setter[,fdel[,doc]]])

class mymoney():
    def __init__(self,money):
        self.__money = money
    def getmoney(self):
        print("inside the getmoney")
        return self.__money
    def setmoney(self,money):
        print("inside the setmoney")
        self.__money = money
    moneymoney =property(getmoney,setmoney) #新式PYTHON風格  property(getter[,setter[,fdel[,doc]]])
    

Ninimoney = mymoney(100)
print(Ninimoney.moneymoney)
Ninimoney.moneymoney = 90
print(Ninimoney.moneymoney)

 property(getter[,setter[,fdel[,doc]]])

getter 獲取屬性

setter 設定屬性

fdel 刪除屬性

doc 屬性描述

傳回的是新式屬性

裝飾器@property

@property 放在getter前面

@ moneymoney .setter 放在setter前面

class mymoney():
    def __init__(self,money):
        self.__money = money
    @property
    def moneymoney(self):
        print("inside the getmoney")
        return self.__money
    @moneymoney.setter
    def moneymoney(self,money):
        print("inside the setmoney")
        self.__money = money
    
    

Ninimoney = mymoney(100)
print(Ninimoney.moneymoney)
Ninimoney.moneymoney = 90
print(Ninimoney.moneymoney)

執行結果

圓面積

class maru():
    def __init__(self,r):
        self.__r = r
    @property
    def area(self):
        return self.__r**2*3.14
obj= maru(10)
print(obj.area)

類別方法@Classmethod

第一個參數習慣用 cls

class Keisan():
    keisan = 0
    def __init__(self):
        Keisan.keisan += 2
    @classmethod
    def show_keisan(cls):
        print("keisan=",cls.keisan)
        print("keisan",Keisan.keisan)
ichi = Keisan()
ni = Keisan()
san =Keisan()
yon =Keisan()
Keisan.show_keisan()

執行結果

靜態方法@staticmethod

class HI():
    @staticmethod
    def hi():
        print("Ye")
HI.hi()

執行結果