Docker部署Redis叢集
阿新 • • 發佈:2021-07-11
面向物件進階
@property裝飾器
不建議將屬性設定為私有的,但是如果直接將屬性暴露給外界也是有問題的,比如我們沒有辦法檢查賦給屬性的值是否有效。我們之前的建議是將屬性命名以單下劃線開頭,通過這種方式來暗示屬性是受保護的,不建議外界直接訪問,那麼如果想訪問屬性可以通過屬性的getter(訪問器)和setter(修改器)方法進行對應的操作。如果要做到這點,就可以考慮使用@property包裝器來包裝getter和setter方法,使得對屬性的訪問既安全又方便
class Persion(object): def __init__(self, name, age): self._name = name self._age = age #訪問器 @property def name(self): return self._name @property def age(self): return self._age #修改器 @age.setter def age(self, age): self._age = age def play(self): if self._age <= 16: print("%s正在玩飛行棋."%self._name) else: print('%s正在玩鬥地主'%self._name) def main(): person = Persion('wdc', 12) person.play() person.age = 22 person.play() if __name__ == '__main__': main()
__slots__
動態語言允許我們在程式執行時給物件繫結新的屬性或方法,當然也可以對已經繫結的屬性和方法進行解繫結。但是如果我們需要限定自定義型別的物件只能繫結某些屬性,可以通過在類中定義__slots__變數來進行限定。需要注意的是__slots__的限定只對當前類的物件生效,對子類並不起任何作用。
class Persion(object): __slots__= ('_name', '_age', '_gender') def __init__(self, name, age): self._name = name self._age = age #訪問器 @property def name(self): return self._name @property def age(self): return self._age #修改器 @age.setter def age(self, age): self._age = age def play(self): if self._age <= 16: print("%s正在玩飛行棋."%self._name) else: print('%s正在玩鬥地主'%self._name) def main(): person = Persion('wdc', 12) person.play() person.age = 22 person.play() if __name__ == '__main__': main()
靜態方法和類方法
例如我們定義一個“三角形”類,通過傳入三條邊長來構造三角形,並提供計算周長和麵積的方法,但是傳入的三條邊長未必能構造出三角形物件,因此我們可以先寫一個方法來驗證三條邊長是否可以構成三角形,這個方法很顯然就不是物件方法,因為在呼叫這個方法時三角形物件尚未創建出來(因為都不知道三條邊能不能構成三角形),所以這個方法是屬於三角形類而並不屬於三角形物件的。我們可以使用靜態方法來解決這類問題
from math import sqrt class Triangle(object): def __init__(self, a, b, c): self._a = a self._b = b self._c = c @staticmethod def is_valid(a, b, c): return a + b >c and a + c >b and b + c >a def perimeter(self): return self._a + self._b + self._c def area(self): half = self.perimeter() / 2 return sqrt(half * (half - self._a) * (half - self._b) * (half - self._c)) def main(): a, b, c = 3, 4, 5 # 靜態方法和類方法都是通過給類發訊息來呼叫的 if Triangle.is_valid(a, b, c): t = Triangle(a, b, c) print(t.perimeter()) # 也可以通過給類發訊息來呼叫物件方法但是要傳入接收訊息的物件作為引數 # print(Triangle.perimeter(t)) print(t.area()) # print(Triangle.area(t)) else: print('無法構成三角形.') if __name__ == '__main__': main()
和靜態方法比較類似,Python還可以在類中定義類方法,類方法的第一個引數約定名為cls,它代表的是當前類相關的資訊的物件(類本身也是一個物件,有的地方也稱之為類的元資料物件),通過這個引數我們可以獲取和類相關的資訊並且可以創建出類的物件,
from time import clock, time, localtime, sleep
class Clock(object):
"""數字時鐘"""
def __init__(self, hour=0, minute=0, second=0):
self._hour = hour
self._minute = minute
self._second = second
@classmethod
def now(cls):
ctime = localtime(time())
return cls(ctime.tm_hour, ctime.tm_min, ctime.tm_sec)
def run(self):
"""RUN"""
self._second += 1
if self._second == 60:
self._second = 0
self._minute = self._minute + 1
if self._minute == 60:
self._minute = 0
self._hour = self._hour + 1
if self._hour == 24:
self._hour =0
def show(self):
"""顯示時間-"""
return "%02d:%02d:%02d" %(self._hour, self._minute, self._second)
def main():
#通過類方法建立物件並獲取時間
clock = Clock.now()
while True:
print(clock.show())
sleep(1)
clock.run()
if __name__ == '__main__':
main()
類之間的關係
簡單的說,類和類之間的關係有三種:is-a、has-a和use-a關係。
is-a關係也叫繼承或泛化,比如學生和人的關係、手機和電子產品的關係都屬於繼承關係。
has-a關係通常稱之為關聯,比如部門和員工的關係,汽車和引擎的關係都屬於關聯關係;關聯關係如果是整體和部分的關聯,那麼我們稱之為聚合關係;如果整體進一步負責了部分的生命週期(整體和部分是不可分割的,同時同在也同時消亡),那麼這種就是最強的關聯關係,我們稱之為合成關係。
use-a關係通常稱之為依賴,比如司機有一個駕駛的行為(方法),其中(的引數)使用到了汽車,那麼司機和汽車的關係就是依賴關係。
繼承和多型
一種做法就是讓一個類從另一個類那裡將屬性和方法直接繼承下來,從而減少重複程式碼的編寫。提供繼承資訊的我們稱之為父類,也叫超類或基類;得到繼承資訊的我們稱之為子類,也叫派生類或衍生類。子類除了繼承父類提供的屬性和方法,還可以定義自己特有的屬性和方法,所以子類比父類擁有的更多的能力,在實際開發中,我們經常會用子類物件去替換掉一個父類物件,這是面向物件程式設計中一個常見的行為,對應的原則稱之為里氏替換原則。
class Persion(object):
"""人"""
def __init__(self, name, age):
self._name = name
self._age = age
@property
def name(self):
return self._name
@property
def age(self):
return self._age
@age.setter
def age(self, age):
self._age = age
def play(self):
print('%s正在愉快的玩耍' % self.name)
def watch(self):
if self.age >= 18:
print('%s正在觀看愛情片.' %self.name)
else:
print('%s正在觀看動畫片.' %self.name)
class student(Persion):
"""學生"""
def __init__(self, name, age, grade):
super().__init__(name, age)
self._grade = grade
@property
def grade(self):
return self._grade
@grade.setter
def grade(self, grade):
self._grade = grade
def study(self, course):
self._course = course
print('%s的%s正在學習%s' % (self.grade, self.name, self._course))
class Teacher(Persion):
"""老師"""
def __init__(self, name, age, title):
super().__init__(name, age)
self._title = title
@property
def title(self):
return self._title
@title.setter
def title(self, title):
self._title = title
def teach(self, course):
print('%s%s正在講%s.' % (self._name, self._title, course))
def main():
stu = student('wxc', 14, '初三')
stu.play()
stu.watch()
stu.study('Math')
t = Teacher('fwm', 20, '教授')
t.teach('Python程式設計')
if __name__ == '__main__':
main()
子類在繼承了父類的方法後,可以對父類已有的方法給出新的實現版本,這個動作稱之為方法重寫(override)。通過方法重寫我們可以讓父類的同一個行為在子類中擁有不同的實現版本,當我們呼叫這個經過子類重寫的方法時,不同的子類物件會表現出不同的行為,這個就是多型(poly-morphism)
from abc import ABCMeta, abstractmethod
class Pet(object, metaclass=ABCMeta):
"""寵物"""
def __init__(self, nickname):
self._nickname = nickname
@abstractmethod #加上@abstractmethod裝飾器後嚴格控制子類必須實現這個方法
def make_voice(self):
"""發出聲音"""
pass
class Dog(Pet):
"""狗"""
def make_voice(self):
print('%s: 汪汪汪...' % self._nickname)
class Cat(Pet):
"""貓"""
def make_voice(self):
print('%s: 喵...喵...' % self._nickname)
def main():
pets = [Dog('旺財'), Cat('凱蒂'), Dog('大黃')]
for pet in pets:
pet.make_voice()
if __name__ == '__main__':
main()
"""
某公司有三種類型的員工 分別是部門經理、程式設計師和銷售員
需要設計一個工資結算系統 根據提供的員工資訊來計算月薪
部門經理的月薪是每月固定15000元
程式設計師的月薪按本月工作時間計算 每小時150元
銷售員的月薪是1200元的底薪加上銷售額5%的提成
"""
from abc import ABCMeta, abstractmethod
class Employee(object, metaclass=ABCMeta):
"""初始化"""
def __init__(self, name):
self._name = name
@property
def name(self):
return self._name
@abstractmethod
def get_salary(self):
"""薪資"""
pass
class Manager(Employee):
"""部門經理"""
def get_salary(self):
return 15000.0
class Programmer(Employee):
"""程式設計師"""
def __init__(self, name, hours=0):
super().__init__(name)
self._hours = hours
@property
def hours(self):
return self._hours
@hours.setter
def hours(self, hours):
self._hours = hours if hours > 0 else 0
def get_salary(self):
return 150.0 * self._hours
class Salesman(Employee):
"""銷售員"""
def __init__(self, name, sales=0):
super().__init__(name)
self._sales = sales
@property
def sale(self):
return self._sales
@sale.setter
def sale(self, sales):
self._sales = sales if sales > 0 else 0
def get_salary(self):
return self._sales * 0.05 + 1200.0
def main():
emps = [
Manager('LB'), Programmer('Zgl'),
Manager('Cc'), Salesman('Gy'),
Salesman('Zf'), Programmer('X'),
Programmer('Zy')
]
for emp in emps:
if isinstance(emp, Programmer):
emp.hours = int(input('請輸入%s的工作的時間:' % emp.name))
elif isinstance(emp, Salesman):
emp.sale = int(input('請輸入%s的銷售總額:' % emp.name))
print('%s 本月的工資為: %s¥' %(emp.name, emp.get_salary()))
if __name__ == '__main__':
main()