27面向對象2_屬性裝飾器

 

目錄python

屬性裝飾器... 1程序員

對象的銷燬:... 3網絡

overload方法重載:... 4app

習題:... 4dom

 

 

 

屬性裝飾器

對用戶來講,屬性裝飾器包裝後的這種用法好,只記一種便可,如stu1.chinesestu1.chinese=100del stu1.chinese;對程序員來講,兩種寫法的代碼量並無減小;ide

查看@property源碼,class property(object)python3的類祖先爲objectdef __init__(self,fget=None,fset=None,fdel=None,doc=None)函數

兩種方式:工具

方一:@property@chinese.setter@chinese.deleterthis

方二:english = property(lambda self: self._english,setenglish)spa

 

通常好的設計,把實例的屬性保護起來,不讓外部直接訪問,外部使用getter讀取屬性和setter設置屬性;

property裝飾器,後面跟的函數名就是之後的屬性名,它就是getter,這個必須有,有了它至少是隻讀屬性;

setter裝飾器,與屬性名同名,且接收2個參數,第一個是self,第二個是將要賦值的值,有了它,屬性可寫;

deleter裝飾器,可控制是是否刪除屬性,不多用;

property裝飾器必須在前,setterdeleter裝飾器在後;

property裝飾器能經過簡單的方式,把對方法的操做變成對屬性的訪問,並起到了必定隱藏效果;

 

注:

類設計:自圓其說;客戶滿意;

pycharmstu1.__後面屬性內容不會提示,即認爲解釋器要隱藏的東西;

 

例:

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')

 

 

 

overload方法重載:

python沒有重載;python不須要重載;其它語言都有重載的概念;

所謂重載,即同一個方法名,但參數數量、類型不同,就是同一個方法的重載;

python中,方法(函數)定義裏,形參很是靈活,不須要指定類型,就算指定了也只是一個說明而非約束,參數個數也不固定(可變參數),一個函數的定義可實現不少種不一樣形式實參的調用,因此python不須要方法重載;

 

注:

標識符覆蓋,override重寫;

靜態編譯型語言,標識符同樣的兩個可同時用,多態;

python天生就支持多態(多種類型),如函數級的多態,def add(x,y)intstr都支持,會自動識別,一個函數對多種形態(多個數據類型)進行處理,甚至返回多種形態;

面向對象的多態,繼承和覆蓋override

繼承,蓋住,不是有你沒我,有我沒你,而是我在我優先,我不在你重見天日,相似實例屬性和類屬性,有優先問題;

 

encapsulation封裝:

面向對象的三要素之一;

將數據和操做組織到類中,即屬性和方法;

將數據隱藏起來,給使用者提供操做,使用者經過操做就可獲取或修改數據,gettersetter

經過訪問控制,暴露適當的數據和操做給用戶,該隱藏的隱藏起來,保護成員或私有成員;

 

 

 

習題:

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、記錄車的品牌markcolor顏色、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())

相關文章
相關標籤/搜索