您好,登錄后才能下訂單哦!
?
目錄
屬性裝飾器... 1
對象的銷毀:... 3
overload方法重載:... 4
習題:... 4
?
?
?
對用戶來說,屬性裝飾器包裝后的這種用法好,只記一種即可,如stu1.chinese、stu1.chinese=100、del stu1.chinese;對程序員來說,兩種寫法的代碼量并沒有減少;
查看@property源碼,class property(object),python3的類祖先為object,def __init__(self,fget=None,fset=None,fdel=None,doc=None);
兩種方式:
方一:@property、@chinese.setter、@chinese.deleter
方二:english = property(lambda self: self._english,setenglish)
?
一般好的設計,把實例的屬性保護起來,不讓外部直接訪問,外部使用getter讀取屬性和setter設置屬性;
property裝飾器,后面跟的函數名就是以后的屬性名,它就是getter,這個必須有,有了它至少是只讀屬性;
setter裝飾器,與屬性名同名,且接收2個參數,第一個是self,第二個是將要賦值的值,有了它,屬性可寫;
deleter裝飾器,可控制是是否刪除屬性,很少用;
property裝飾器必須在前,setter、deleter裝飾器在后;
property裝飾器能通過簡單的方式,把對方法的操作變成對屬性的訪問,并起到了一定隱藏效果;
?
注:
類設計:自圓其說;客戶滿意;
pycharm中stu1.__后面屬性內容不會提示,即認為解釋器要隱藏的東西;
?
例:
class Person:
??? def __init__(self,chinese,english,history):
??????? self._chinese = chinese?? #對于要隱藏的實例屬性要用_或__,下面要提供獲取或修改屬性的方法,且一定要用方法來操作,不要直接操作
??????? self._english = english
??????? self.__history = history
?
??? def getscore(self):
??????? return self._chinese,self._english,self.__history
?
??? def gethistory(self):?? #實例屬性的獲取getter,經常用
??????? return self.__history
?
??? def sethistory(self,value):?? #實例屬性的設置setter,經常用,即self.__history該屬性可rw讀寫
??????? self.__history = value
?
??? def getenglish(self):?? #self._english該屬性只可r讀,另可w不可r用處不大
??????? return self._english
?
stu1 = Person(80,90,88)
print(stu1.gethistory())? ?#這樣的事很多,每次都用獲取方法得到或設置方法修改,這樣很麻煩
print(stu1.getscore())
輸出:
88
(80, 90, 88)
?
例:
class Person:
??? def __init__(self,chinese,english,history):
??????? self._chinese = chinese
??????? self._english = english
??????? self.__history = history
?
??? @property?? #屬性裝飾器,將方法轉為屬性,方一,通過stu1.chinese該屬性可讀
??? def chinese(self):
??????? return self._chinese
?
??? @chinese.setter?? #此處chinese即為上面方法轉屬性的chinese,通過stu1.chinese=100該屬性可寫
??? def chinese(self,value):
??????? self._chinese = value
?
??? @chinese.deleter?? #動態的刪除屬性,慎用,通過del stu1.chinese將自動執行該方法
??? def chinese(self):
??????? # del self._chinese
??????? print('del chinese')
?
?? ?# def getenglish(self): ??#可將此段簡寫為lambda self: self._english
? ??# ????return self._english
?
??? # english = property(getenglish) ??#通過stu1.english該屬性可讀
?
??? def setenglish(self,value):
??????? self._english = value
?
??? english = property(lambda self: self._english,setenglish)?? #方二,通過stu1.english=120該屬性可讀可寫,類庫中使用此方式的多
?
??? def __del__(self):
??????? print('leaving')
?
stu1 = Person(80,90,88)
print(stu1.chinese)?? #r
stu1.chinese = 100?? #w
print(stu1.chinese)
del stu1.chinese?? #del
輸出:
80
100
del chinese
90
120
leaving
?
?
?
類中可定義__del__方法,稱為析構函數(方法);
作用:銷毀類的實例時調用,以釋放占用的資源;收尾工作,把打開的資源(連接網絡、DB、打開文件等操作)關閉掉,不用這些實例時要銷毀,同with語句;
由于python實現了垃圾回收機制,會自動執行該方法,不能確定何時執行,有必要請使用del語句手動調用這個方法刪除實例;
?
def __del__(self):
???????? print('leaving')
?
?
?
python沒有重載;python不需要重載;其它語言都有重載的概念;
所謂重載,即同一個方法名,但參數數量、類型不一樣,就是同一個方法的重載;
python中,方法(函數)定義里,形參非常靈活,不需要指定類型,就算指定了也只是一個說明而非約束,參數個數也不固定(可變參數),一個函數的定義可實現很多種不同形式實參的調用,所以python不需要方法重載;
?
注:
標識符覆蓋,override重寫;
靜態編譯型語言,標識符一樣的兩個可同時用,多態;
python天生就支持多態(多種類型),如函數級的多態,def add(x,y),int和str都支持,會自動識別,一個函數對多種形態(多個數據類型)進行處理,甚至返回多種形態;
面向對象的多態,繼承和覆蓋override;
繼承,蓋住,不是有你沒我,有我沒你,而是我在我優先,我不在你重見天日,類似實例屬性和類屬性,有優先問題;
?
encapsulation封裝:
面向對象的三要素之一;
將數據和操作組織到類中,即屬性和方法;
將數據隱藏起來,給使用者提供操作,使用者通過操作就可獲取或修改數據,getter,setter;
通過訪問控制,暴露適當的數據和操作給用戶,該隱藏的隱藏起來,保護成員或私有成員;
?
?
?
1、隨機整數生成類,可以指定一批生成的個數,可指定數值的范圍,可調整每批生成數字的個數;
import random
?
class RandomNums:
??? def __init__(self,nums=10,min=0,max=100):
??????? self.nums = nums
??????? self.min = min
??????? self.max = max
?
??? def create(self):
??????? return [random.randint(self.min,self.max) for _ in range(self.nums)]
?
rn = RandomNums(10,0,100)
print(rn.create())
?
#####
#作為工具類實現,提供類方法
?
class RandomNums:
??? @classmethod
??? def create(cls,nums=12,min=1,max=100):
??????? return [random.randint(min,max) for _ in range(nums)]
?
print(RandomNums.create())
?
#####
#使用生成器實現
?
class RandomGenerator:
??? def __init__(self,count=10,start=1,stop=100):
??????? self.count = count
??????? self.start = start
??????? self.stop = stop
??????? self.gen = self._generator()
?
??? def _generator(self):
??????? while True:
??????????? yield random.randint(self.start,self.stop)
?
??? def generate(self):
??????? return [next(self.gen) for _ in range(self.count)]
?
rg = RandomGenerator(10,1,100)
print(rg.generate())
?
#####
?
class RandomGenerator:
??? def __init__(self,count=10,start=1,stop=10):
??????? self.count = count
??????? self.start = start
??????? self.stop = stop
?????? ?self.gen = self._generate()
?
??? def _generate(self):
??????? while True:
??????????? yield [random.randint(self.start,self.stop) for _ in range(self.count)]
?
??? def generate(self,count):
?????? ?self.count = count
??????? return next(self.gen)
?
rg = RandomGenerator()
lst = rg.generate(15)
print(lst)
?
2、使用上題中的類,隨機生成20個數字,兩兩配對形成二維坐標系的坐標,把這些坐標組織起來,并打印輸出;
import random
?
class RandomGenerator:
??? def __init__(self,count=10,start=1,stop=100):
??????? self.count = count
??????? self.start = start
??????? self.stop = stop
??????? self.gen = self._generate()
?
??? def _generate(self):
??????? while True:
??????????? yield [random.randint(self.start,self.stop) for _ in range(self.count)]
?
??? def generate(self,count):
??????? self.count = count
??????? return next(self.gen)
?
class Point:
??? def __init__(self,x,y):
??????? self.x = x
??????? self.y = y
?
??? def __repr__(self):
??????? return '{}:{}'.format(self.x,self.y)
?
rg = RandomGenerator()
?
lst = [Point(x,y) for x,y in zip(rg.generate(12),rg.generate(12))]
# for p in lst:?? #此方式打印,不需要Point類中的__repr__方法
#???? print('{}:{}'.format(p.x,p.y))
print(Point(4,5))
print(lst)
?
3、記錄車的品牌mark、color顏色、price價格、speed速度等特征,并實現增加車輛信息,顯示全部信息的功能;
?
class Car:
??? def __init__(self,mark,color,price,speed):
??????? self.mark = mark
??????? self.color = color
??????? self.price = price
??????? self.speed = speed
?
class CarInfo:
??? def __init__(self):
??????? self.info = []?? #數據在哪,方法就在哪
?
??? def addcar(self,car:Car):
??????? self.info.append(car)
?
??? def getall(self):
??????? return self.info
?
ci = CarInfo()
car = Car('audi','red',100,400)
ci.addcar(car)
print(ci.getall())
注:
修改車輛信息在Car中;
?
4、實現溫度的處理;
攝氏溫度和華氏溫度的轉換:
C = 5 * (F-32) / 9
F = 9 * C / 5 + 32
攝氏溫度與開氏溫度的轉換:
K = C + 273.15
?
class Temperature:
??? def __init__(self,t,unit='c'):
??????? self._c = None
??????? self._f = None
??????? self._k = None
?
??????? if unit == 'f':
??????????? self._f = t
??????????? self._c = self.f2c(t)
??????? elif unit == 'k':
??????????? self._k = t
??????????? self._c = self.k2c(t)
??????? else:
??????????? self._c = t
?
??? @property
??? def c(self):
??????? return self._c
?
??? @property
??? def f(self):
??????? if self._f == None:
??????????? self._f = self.c2f(self._c)
??????? return self._f
?
??? @property
??? def k(self):
??????? if self._k == None:
??????????? self._k = self.c2k(self._c)
??????? return self._k
?
??? @classmethod
??? def f2c(cls,f):
??? ????return 5*(f-32)/9
?
??? @classmethod
??? def f2k(cls,f):
??????? return cls.c2k(cls.f2c(f))
?
??? @classmethod
??? def k2c(cls,k):
??????? return k-273.15
?
??? @classmethod
??? def k2f(cls,k):
??????? return cls.c2f(cls.k2c(k))
?
??? @classmethod
??? def c2k(cls,c):
??????? return c+273.15
?
??? @classmethod
??? def c2f(cls,c):
??????? return 9*c/5+32
?
t = Temperature(100)?? #實例化
print(t.c,t.f,t.k)?? #實例屬性訪問
print(t.f2c(212.0))?? #實例也可以用類方法
?
t = Temperature(373.15,unit='k')
print(t.c,t.f,t.k)
?
print(Temperature.c2f(100))?? #如果只是工具,就用類方法或靜態方法,不用實例化;如果需要為用戶保存數據,且該實例會發生變化,就要實例化
print(Temperature.c2k(100))
print(Temperature.f2k(212))
print(Temperature.f2c(212))
print(Temperature.k2c(373.15))
print(Temperature.k2f(373.15))
?
5、模擬購物車購物;
?
class Color:
??? RED = 0
??? GREEN = 1
??? BLUE = 2
??? GOLDEN = 3
??? BLACK = 4
??? OTHER = 1000
?
class Item:
??? def __init__(self,**kwargs):
??????? self.__spec = kwargs
?
??? def __repr__(self):
??????? return str(sorted(self.__spec.items()))
?
class Cart:
??? def __init__(self):
??????? self.items = []
?
??? def additem(self,item:Item):
??????? self.items.append(item)
?
??? def getall(self):
??????? return self.items
?
mycart = Cart()
myphone = Item(mark = 'huawei',color = Color.GOLDEN,price=3000)
mycart.additem(myphone)
print(mycart.getall())
?
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。