軟件質量屬性包含:成本,性能,可靠性,安全性,可維護性,可移植性,可伸縮性,可擴展性等python
country='American' def study(): print('study english') class Student(): country = 'China' def __init__(self, ID, NAME, SEX, PROVINCE,country): self.id = ID self.name = NAME self.sex = SEX self.province = PROVINCE self.country = country def search_score(self): print('全局的',country) study() #全局的 print('類裏的', Student.country) Student.study(self) #類裏的 print('對象的', self.country) #對象有就從自身找,沒有就從類中找 self.study() # def study(self): print('study',self.country) s1 = Student('3718818181', 'alex', 'female', 'shanxi','Singapore') s1.search_score() """ 全局的 American study english 類裏的 China study Singapore 對象的 Singapore study Singapore """
在obj.name會先從obj本身的名稱空間裏找name,找不到則去類中找,類也找不到就找父類...最後都找不到就拋出異常git
class A: def fa(self): print('from A') def test(self): self.fa() class B(A): def fa(self): print('from B') b=B() b.test() #from B """ 從本身找b.test(),沒有找類B,也沒有找類A,找到後執行self.fa(), self指的是b對象,而後又從本身找fa(),沒有就去類B中找fa(),找到了 因此打印 from B """ class C: def __fa(self): #_C__fa print('from C') def test(self): self.__fa() #slef._C__fa __在定義階段就會變形 class D(C): def __fa(self): #_D__fa print('from D') d=D() d.test() #from C """ __不能被子類繼承和覆蓋 """
封裝在於明確區份內外, 類的實現者不須要讓類的調用者知道具體的實現過程,隔離了複雜度,同時也提高了安全性,類的實現者能夠修改封裝內的東西而不影響外部調用者的代碼。編程
使用構造方法將屬性封裝到某個具體對象中,而後經過對象直接或者self間接獲取被封裝的屬性,類自己就是一種封裝的體現,它將數據與專門操做該數據的功能整合到一塊兒。安全
import math class Circle: def __init__(self,radius): #圓的半徑radius self.radius=radius @property #被@property裝飾的方法,調用的時候能夠不用加括號,area=property(area) def area(self): return math.pi * self.radius**2 #計算面積 @property def perimeter(self): return 2*math.pi*self.radius #計算周長 c=Circle(3) print(c.area) print(c.perimeter)
#被property裝飾的屬性會優先於對象的屬性被使用,只有在屬性sex定義property後才能定義sex.setter,sex.deleter class People: def __init__(self,name,SEX): self.name=name # self.__sex=SEX #這不調用@sex.setter def sex(self,value):方法 由於設置的是__sex 不是 sex,或者說__sex沒有被@property裝飾 self.sex=SEX #①由於sex被@property裝飾,因此self.sex=SEX是去找@sex.setter def sex(self,value): 方法,而不是給對象賦值 @property def sex(self): return self.__sex #p1.__sex @sex.setter def sex(self,value): print('...') if not isinstance(value,str): raise TypeError('性別必須是字符串類型') self.__sex=value #② male給了value , self.__sex='male' @sex.deleter #del p1.sex的時候調用 def sex(self): del self.__sex #del p1.__sex p1=People('alex','male') #會調用 @sex.setter def sex(self,value): 方法是由於__init__中 self.sex=SEX 是給sex設置值了 p1.sex='female' #會調用@sex.setter def sex(self,value): 方法 del p1.sex print(p1.sex) #AttributeError: 'People' object has no attribute '_People__sex'
import time class Date: def __init__(self,year,month,day): self.year=year self.month=month self.day=day @classmethod #把一個方法綁定給類:類.綁定到類的方法(),會把類自己當作第一個參數自動傳給綁定到類的方法 def now(cls): #用Date.now()的形式去產生實例,該實例用的是當前時間 t=time.localtime() #獲取結構化的時間格式 obj=cls(t.tm_year,t.tm_mon,t.tm_mday) #新建實例而且返回 return obj @classmethod def tomorrow(cls):#用Date.tomorrow()的形式去產生實例,該實例用的是明天的時間 t=time.localtime(time.time()+86400) return cls(t.tm_year,t.tm_mon,t.tm_mday) class EuroDate(Date): def __str__(self): return '年:%s,月:%s,日:%s' %(self.year,self.month,self.day) e1=EuroDate.now() print(e1) e1=EuroDate(1,1,1) print(e1) """ 年:2019,月:3,日:17 年:1,月:1,日:1 """
import time class Date: def __init__(self,year,month,day): self.year=year self.month=month self.day=day @staticmethod def now(): #用Date.now()的形式去產生實例,該實例用的是當前時間 t=time.localtime() #獲取結構化的時間格式 obj=Date(t.tm_year,t.tm_mon,t.tm_mday) #新建實例而且返回 return obj @staticmethod def tomorrow():#用Date.tomorrow()的形式去產生實例,該實例用的是明天的時間 t=time.localtime(time.time()+86400) return Date(t.tm_year,t.tm_mon,t.tm_mday) d1=Date.now() print(d1.year,d1.month,d1.day) d2=Date.tomorrow() print(d2.day)
繼承是一種建立新類的方式,新建的類能夠繼承一個或多個父類(python支持多繼承),父類又可稱爲基類或超類,新建的類稱爲派生類或子類。解決了代碼重複的問題服務器
#多態:同一種事物的多種形態,動物分爲人類,豬類(在定義角度) class Animal: def run(self): raise AttributeError('子類必須實現這個方法') class People(Animal): def run(self): print('人正在走') class Pig(Animal): def run(self): print('pig is walking') class Dog(Animal): def run(self): print('dog is running') peo1=People() pig1=Pig() d1=Dog() peo1.run() pig1.run() d1.run() #多態性:一種調用方式,不一樣的執行效果(多態性) def func(obj): obj.run() func(peo1) func(pig1) func(d1) # peo1.run() # pig1.run() # 多態性依賴於: # 1.繼承 # 2. ##多態性:定義統一的接口, def func(obj): #obj這個參數沒有類型限制,能夠傳入不一樣類型的值 obj.run() #調用的邏輯都同樣,執行的結果卻不同 func(peo1) func(pig1)
軟件重用的重要方式除了繼承以外還有另一種方式,即:組合 組合指的是,在一個類中以另一個類的對象做爲數據屬性,稱爲類的組合ide
當類之間有顯著不一樣,而且較小的類是較大的類所須要的組件時,用組合比較好函數式編程
class Teacher: def __init__(self,name,sex,course): self.name=name self.sex=sex self.course=course class Student: def __init__(self,name,sex,course): self.name=name self.sex=sex self.course=course class Course: def __init__(self,name,price,peroid): self.name=name self.price=price self.period=peroid python_obj=Course('python',15800,'7m') t1=Teacher('egon','male',python_obj) s1=Student('cobila','male',python_obj) print(s1.course.name) print(t1.course.name)
class Animal: def run(self): raise AttributeError('子類必須實現這個方法') def speak(self): raise AttributeError('子類必須實現這個方法') class People(Animal): def run(self): print('人正在走') def speak(self): print('說話') class Pig(Animal): def run(self): print('pig is walking') def speak(self): print('哼哼哼') # peo1=People() # pig1=Pig() # # peo1.run() # pig1.run()
import abc #抽象類:本質仍是類,與普通類額外的特色的是:加了裝飾器的函數,子類必須實現他們 class Animal(metaclass=abc.ABCMeta): tag='123123123123123' @abc.abstractmethod def run(self): pass @abc.abstractmethod def speak(self): pass class People(Animal): def run(self): pass def speak(self): pass peo1=People() print(peo1.tag)
經過字符串的形式操做對象相關的屬性。python中的一切事物都是對象(均可以使用反射)函數
import sys def add(): print('add') def change(): print('change') def search(): print('search') def delete(): print('delete') this_module=sys.modules[__name__] #獲取當前模塊 while True: cmd=input('>>:').strip() if not cmd:continue if hasattr(this_module,cmd): func=getattr(this_module,cmd) func() #多分支判斷方式1: # func_dic={ # 'add':add, # 'change':change, # 'search':search, # 'delete':delete # } # # while True: # cmd=input('>>:').strip() # if not cmd:continue # if cmd in func_dic: # func=func_dic.get(cmd) # func() #多分支判斷方式2: # class Service: # def run(self): # while True: # inp = input('>>: ').strip() # cmd='get a.txt' # cmds = inp.split() # cmds=['get','a.txt'] # if hasattr(self, cmds[0]): # func = getattr(self, cmds[0]) # func(cmds) # # def get(self, cmds): # print('get.......', cmds) # # def put(self, cmds): # print('put.......', cmds) # # obj = Service() # obj.run()
#ftpclient.py class FtpClient: 'ftp客戶端,可是還麼有實現具體的功能' def __init__(self,addr): print('正在鏈接服務器[%s]' %addr) self.addr=addr def test(self): print('test') def get(self): print('get------->') #ftpserver.py #服務端同窗能夠不用非等着客戶端同窗寫完代碼纔去實現 import ftpclient f1=ftpclient.FtpClient('192.168.1.1') if hasattr(f1,'get'): #有就執行沒有就執行其餘邏輯 func=getattr(f1,'get') func() else: print('其餘邏輯')
#!/usr/bin/env python # -*- coding:utf-8 -*- # 先定義類 後產生對象 class Animal: def eat(self): print('is eating') class Student(Animal): # 繼承,可繼承多個,用mro()查看繼承關係 school = 'Peking University' # 類的數據屬性 count = 0 def __init__(self, name, age): # 類的函數屬性,也就是對象的綁定方法() self.name = name self.age = age Student.count += 1 def learn(self): print('%s is learning' % self.name) def eat(self): # 重寫父類方法 print('Wash your hands before eating') # 加入本身新功能 # Peo2.eat(self) #重用父類的方法 # super(Student,self).eat() #重用父類的方法 super().eat() # 重用父類的方法 super是按照mro的順序查找 """ 類: 一、類的數據屬性是全部對象共享的,id都同樣 二、類的函數屬性是綁定給對象用的,obj.method稱爲綁定方法,綁定到不一樣的對象是不一樣的綁定方法,對象調用綁定方式時,會把對象自己看成第一個傳入,傳給self (綁定到對象的方法的這種自動傳值的特徵,決定了在類中定義的函數都要默認寫一個參數self,self能夠是任意名字,可是約定俗成地寫出self。 ) 三、__init__方法 (1)、該方法內能夠有任意的python代碼 (2)、必定不能有返回值 繼承: """ print(issubclass(Student, Animal))# 檢查Student類是不是Animal類的派生類 # 增 Student.country = 'China' # 刪 del Student.country # 改 Student.school = 'Tsinghua University' # 查 print(Student.__dict__) # 查看類的名稱空間 print(Student.school) print(Student.learn) print(Student.__mro__) # 查看類的繼承關係 print(Student.__bases__) # 查看類的父類 """ 對象: 屬性查找順序:在obj.name會先從obj本身的名稱空間裏找name,找不到則去類中找,類也找不到就找父類...最後都找不到就拋出異常 """ stu = Student('tom', 18) # 實例化一個對象 print(isinstance(stu,Student)) #obj是不是類 cls 的對象 # 增 stu.gender = 'male' # 刪 del stu.gender # 改 stu.age = 28 # 查 print(stu.__dict__) print(stu.name) stu.eat() """ super 按照mro的順序查找 """ class A: def f1(self): print('from A') super().f1() class B: def f1(self): print('from B') class C(A, B): pass print(C.mro()) # [<class '__main__.C'>, # <class '__main__.A'>, # <class '__main__.B'>, # <class 'object'>] c = C() c.f1() # 打印 from A from B """ 封裝:類的實現者不須要讓類的調用者知道具體的實現過程 """ """ __私有屬性,私有方法 (類的定義極端就已經變形了) 這種變形的特色: 一、在類外部沒法直接obj.__AttrName 二、在類內部是能夠直接使用:obj.__AttrName 三、子類沒法覆蓋父類__開頭的屬性 四、在定義階段就會變形,也就是說__開頭的屬性(變量和函數)不能被子類繼承 由於在定義階段__屬性名就變成了_父類名__屬性名。 """ class A: def __foo(self): # _A__foo print('A.foo') def bar(self): print('A.bar') self.__foo() # self._A__foo() class B(A): def __foo(self): # _B__foo print('B.foo') b = B() b.bar() """ @property 類的靜態屬性,類方法,類的靜態方法 在類內部定義的函數,分爲兩大類: 一:綁定方法:綁定給誰,就應該由誰來調用,誰來調用就回把調用者看成第一個參數自動傳入 綁定到對象的方法:在類內定義的沒有被任何裝飾器修飾的 綁定到類的方法:在類內定義的被裝飾器classmethod修飾的方法 二:非綁定方法:沒有自動傳值這麼一說了,就類中定義的一個普通工具,對象和類均可以使用 非綁定方法:不與類或者對象綁定 """ import hashlib, time class Teacher: def __init__(self, name, weight, height): self.name = name self.weight = weight self.height = height self.id = self.create_id() @property # 類的靜態屬性@property 封裝的部分體現 def bmi(self): return self.weight / (self.height ** 2) @classmethod # 綁定到類的方法 def talk(cls): print('is talking') @staticmethod # 非綁定方法 類的靜態方法,就是一個普通工具 def create_id(): m = hashlib.md5(str(time.time()).encode('utf-8')) return m.hexdigest() def play(self): # 綁定到對象的方法 print('is playing') t = Teacher('jack', 80, 1.8) print(t.bmi) print(t.id) """ 多態: 不考慮對象的類型,直接使用對象,也就是不一樣類的實例調用相同的方法,實現的過程不同。 多態怎麼來的? 1,不一樣的類先繼承基類, 2,而後不一樣類的實例調用相同的方法(這個相同的方法是從基類那繼承來的) 抽象類: 本質仍是類,於普通類不同的是,加了裝飾器的函數,子類必須實現他們,也就是抽象類的方法必需要重寫 """ import abc class People(metaclass=abc.ABCMeta): # 抽象類,只能被繼承,不能被實例化 @abc.abstractmethod def answer(self): pass class Chinese(People): def answer(self): # 抽象類的方法必需要重寫 print('用中文答辯') class English(People): def answer(self): # 抽象類的方法必需要重寫 print('use english') chi = Chinese() eng = English() def ans(obj): # 相同的調用方式 obj.answer() ans(chi) # 相同的調用方式 多態 ans(eng) # 相同的調用方式 """ 類的組合: 軟件重用的重要方式除了繼承以外還有另一種方式,即:組合 組合指的是,在一個類中以另一個類的對象做爲數據屬性,稱爲類的組合 """ class Date: def __init__(self, year, mon, day): self.year = year self.mon = mon self.day = day def tell_info(self): print('My birthday is %s-%s-%s' % (self.year, self.mon, self.day)) d = Date(1986, 6, 26) stu2 = Student('rose', 88) stu2.birth = d stu2.birth.tell_info() """ 反射:經過字符串映射到對象的屬性 setattr(obj,'sex','male') getattr(obj,'namexxx',None) hasattr(obj,'talk') delattr(obj,'age') """ class Service: def run(self): while True: inp = input('>>: ').strip() # cmd='get a.txt' cmds = inp.split() # cmds=['get','a.txt'] if hasattr(self, cmds[0]): func = getattr(self, cmds[0]) func(cmds) def get(self, cmds): print('get.......', cmds) def put(self, cmds): print('put.......', cmds) obj = Service() # obj.run()