Python面向對象

三種編程方法論

  • 面向過程:把複雜的任務一步一步分解成簡單的任務。
  • 函數式編程:思想上接近於數學運算,根據某種方式,根據方式得出的結果。
  • 面向對象編程:一種編程方式,須要使用「類」和「對象」來實現,其實就是對「類」和「對象的」使用

軟件質量屬性

軟件質量屬性包含:成本,性能,可靠性,安全性,可維護性,可移植性,可伸縮性,可擴展性等python

面向過程

  • 概念:核心是「過程」二字,「過程」指的是解決問題的步驟,即先幹什麼再幹什麼......,把這個大的問題分解成不少個小問題或子過程,這些子過程在執行的過程當中繼續分解,直到小問題足夠簡單到能夠在一個小步驟範圍內解決。
  • 優勢:複雜的問題流程化,進而簡單化
  • 缺點:擴展性極差
  • 應用場景:通常用於那些功能一旦實現以後就不多須要改變的場景, 若是你只是寫一些簡單的腳本,去作一些一次性任務,用面向過程的方式是極好的,著名的例子有Linux內核,git,以及Apache HTTP Server等。但若是你要處理的任務是複雜的,且須要不斷迭代和維護 的, 那仍是用面向對象最方便了。

面向對象編程

  • 概念:核心是「對象」二字,對象就是特徵與技能的結合體。
  • 優勢:可擴展性高
  • 缺點:編程的複雜度高,易出現過分設計的問題
  • 應用場景:應用於需求常常變化的軟件中,通常需求的變化都集中在用戶層,互聯網應用,企業內部軟件,遊戲等都是面向對象的程序設計大顯身手的好地方。

1、名詞解釋

  • :一個類便是對一類擁有相同屬性的對象的抽象、藍圖、原型、模板。在類中定義了這些對象的都具有的屬性(variables(data))、共同的方法
  • 屬性:人類包含不少特徵,把這些特徵用程序來描述的話,叫作屬性,好比年齡、身高、性別、姓名等都叫作屬性,一個類中,能夠有多個屬性
  • 方法:人類不止有身高、年齡、性別這些屬性,還能作好多事情,好比說話、走路、吃飯等,相比較於屬性是名詞,說話、走路是動詞,這些動詞用程序來描述就叫作方法。
  • 實例(對象):一個對象便是一個類的實例化後實例,一個類必須通過實例化後方可在程序中調用,一個類能夠實例化多個對象,每一個對象亦能夠有不一樣的屬性,就像人類是指全部人,每一個人是指具體的對象,人與人以前有共性,亦有不一樣
  • 實例化:把一個類轉變爲一個對象的過程就叫實例化 就是類名+括號,就是在執行類的__init__()方法
  • 構造方法:__init__(...)被稱爲 構造方法或初始化方法,在例實例化過程當中自動執行,目的是初始化實例的一些屬性。每一個實例經過__init__初始化的屬性都是獨有的
  • 析構方法(解構方法):__del__(self)被稱爲 析構方法或解構方法,實例在內存中被刪除時,會自動執行這個方法。

2、類和對象

  • 類中能夠有任意python代碼,這些代碼在類定義階段便會執行
  • 於是會產生新的名稱空間,用來存放類的變量名與函數名,能夠經過 類名.__dict__查看
  • 對於經典類來講咱們能夠經過該字典操做類名稱空間的名字(新式類有限制),但python爲咱們提供專門的.語法
  • 點是訪問屬性的語法,類中定義的名字,都是類的屬性
  • isinstance(obj,cls)檢查obj是不是類 cls 的對象
  • 類的兩種用法:實例化和屬性引用(類的屬性就兩種:變量和函數)
  • 對象也叫實例只有一種用法:屬性引用,就對象自己而言它只有數據屬性
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
"""
類中調用屬性

3、__init__方法

  • 爲對象初始化本身獨有的特徵
  • 該方法內能夠有任意的python代碼
  • 必定不能有返回值*****

4、屬性查找

在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
"""
__不能被子類繼承和覆蓋
"""
屬性查找順序

5、特性1:封裝

封裝在於明確區份內外, 類的實現者不須要讓類的調用者知道具體的實現過程,隔離了複雜度,同時也提高了安全性,類的實現者能夠修改封裝內的東西而不影響外部調用者的代碼。編程

一、構造方法和類自己的包裹

使用構造方法將屬性封裝到某個具體對象中,而後經過對象直接或者self間接獲取被封裝的屬性,類自己就是一種封裝的體現,它將數據與專門操做該數據的功能整合到一塊兒。安全

二、__雙下劃線屬性隱藏

  • 在python中用雙下劃線開頭的方式將屬性隱藏起來,設置成私有的
  • 類中全部雙下劃線開頭的名稱如__x都會在類定義時自動變造成:_類名__x的形式
  • 變形的過程只在類的定義時發生一次,在定義後的賦值操做,不會變形
  • 在繼承中,父類若是不想讓子類覆蓋本身的方法,能夠將方法定義爲私有的

三、裝飾器@property也有封裝的思想

  • @property 類的靜態屬性:
    1. 將一個類的函數定義成特性之後,對象再去使用的時候obj.mbi,根本沒法察覺本身的mbi是執行了一個函數而後計算出來的,
    2. @property這種特性的使用方式遵循了統一訪問的原則
  • @classmethod
    1. 把一個方法綁定給類,會把類自己當作第一個參數自動傳給綁定到類的方法
    2. 類的綁定方法
  • @staticmethod
    1. 被staticmethod裝飾器修飾過的方法,都是解除綁定的方法,實際上就函數:就沒有自動傳值功能了
    2. 解除綁定的方法
  • 凡是定義在類的內部,而且沒有被任何裝飾器修飾過的方法,都是綁定方法:有自動傳值功能
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
#被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'
@property @屬性.setter @屬性.deleter
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
"""
@classmethod
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)
@staticmethod

6、特性2:繼承

繼承是一種建立新類的方式,新建的類能夠繼承一個或多個父類(python支持多繼承),父類又可稱爲基類或超類,新建的類稱爲派生類或子類。解決了代碼重複的問題服務器

一、繼承順序

  • python會計算出一個方法解析順序(mro)列表,這個mro列表就是一個簡單的全部基類的線性順序列表 F.mro()等同於F.__mro__ 注意只有新式類纔有這個方法
  • 子類會先於父類被檢查
  • 多個父類會根據它們在列表中的順序被檢查
  • 若是對下一個類存在兩個合法的選擇,選擇第一個父類
  • 經典類的深度優先查找和新式類的廣度優先查找

二、子類中調用父類的方法

  • 方法一:父類名.父類方法() 父類名.__init__(self,name,speed,load,power)
  • 方法二:【super只能用於新式類】super(本身的類,self).父類的函數名字
    python3中寫法:super().__init__(name,speed,load,power)
    python2中寫法:super(Subway,self).__init__(name,speed,load,power)
  • 兩者使用哪種均可以,但最好不要混合使用,注意區分參數self
  • 這兩種方式的區別是:方式一是跟繼承沒有關係的,而方式二的super()是依賴於繼承的,而且即便沒有直接繼承關係,super仍然會按照mro繼續日後查找
  • super(Subway,self) 就至關於實例自己 在python3中super()等同於super(Subway,self)
  • issubclass(sub, super)檢查sub類是不是 super 類的派生類

三、經典類與新式類

  • 只有在python2中才分新式類和經典類,python3中統一都是新式類
  • 在python2中,沒有顯式的繼承object類的類,以及該類的子類,都是經典類
  • 在python2中,顯式地聲明繼承object的類,以及該類的子類,都是新式類
  • 在python3中,不管是否繼承object,都默認繼承object,即python3中全部類均爲新式類
  • A.__bases__ 或者 A.__mor__查看類A的繼承。mor()方法只在新式類中有

四、繼承和抽象(先抽象再繼承)

  • 抽象即提取相似的部分。
  • 基類就是抽象多個類共同的屬性獲得的一個類。

五、派生

  • 派生就是子類在繼承父類的基礎上衍生出新的屬性。
  • 子類中獨有的,父類中沒有的或子類定義與父類重名的屬性,那麼在調用子類的這個屬性時就以子類本身的爲準。
  • 子類也叫派生類。

7、特性3:多態

  • 多態:指的是一類事物有多種形態,好比動物有多種形態:人,狗,豬
  • 多態性:指在不考慮實例類型的狀況下使用實例,多態性分爲靜態多態性和動態多態性,想一想len 函數的使用
  • 靜態多態性:如任何類型均可以用運算符+進行運算
  • 動態多態性:
  • 實現:不一樣的類先繼承基類,而後不一樣類的實例調用相同的方法(這個相同的方法是從基類那繼承來的)
  • 做用:增長了程序的靈活性和可擴展性,(使用者都是同一種形式去調用)
#多態:同一種事物的多種形態,動物分爲人類,豬類(在定義角度)
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)
多態性

其餘補充

1、類的組合

軟件重用的重要方式除了繼承以外還有另一種方式,即:組合 組合指的是,在一個類中以另一個類的對象做爲數據屬性,稱爲類的組合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)
組合

2、抽象類(接口與歸一化設計)

一、接口

  • 接口:接口提取了一羣類共同的函數,能夠把接口當作一個函數的集合,而後讓子類去實現接口中的函數。
  • 做用:歸一化設計,限制實現接口的類必須按照接口給定的調用方式實現這些方法;對高層模塊隱藏了類的內部實現。
  • hi boy,給我開個查詢接口。。。此時的接口指的是:本身提供給使用者來調用本身功能的方式\方法\入口

二、歸一化

  • 歸一化:就是隻要是基於同一個接口實現的類,那麼全部的這些類產生的對象在使用時,從用法上來講都同樣。
  • 好處:
    1. 歸一化讓使用者無需關心對象的類是什麼,只須要的知道這些對象都具有某些功能就能夠了,這極大地下降了使用者的使用難度。
    2. 歸一化使得高層的外部使用者能夠不加區分的處理全部接口兼容的對象集合
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)
抽象類

四、抽象類與接口

  • 抽象類的本質仍是類,指的是一組類的類似性,包括數據屬性(如all_type)和函數屬性(如read、write),而接口只強調函數屬性的類似性。
  • 抽象類是一個介於類和接口之間的一個概念,同時具有類和接口的部分特性,能夠用來實現歸一化設計

3、類中定義的函數分紅兩大類

一、綁定方法(綁定給誰,誰來調用就自動將它自己看成第一個參數傳入)

  1. 綁定到類的方法:用classmethod裝飾器裝飾的方法。
    • 爲類量身定製
    • 類.bound_method(),自動將類看成第一個參數傳入
    • (其實對象也可調用,但仍將類看成第一個參數傳入)
  2. 綁定到對象的方法:沒有被任何裝飾器裝飾的方法。
    • 爲對象量身定製
    • 對象.bound_method(),自動將對象看成第一個參數傳入
    • (屬於類的函數,類能夠調用,可是必須按照函數的規則來,沒有自動傳值那麼一說)

二、非綁定方法:用staticmethod裝飾器裝飾的方法

  • 不與類或對象綁定,類和對象均可以調用,可是沒有自動傳值那麼一說。就是一個普通工具而已
  • 注意:與綁定到對象方法區分開,在類中直接定義的函數,沒有被任何裝飾器裝飾的,都是綁定到對象的方法,可不是普通函數,對象調用該方法會自動傳值,而staticmethod裝飾的方法,無論誰來調用,都沒有自動傳值一說

4、反射

經過字符串的形式操做對象相關的屬性。python中的一切事物都是對象(均可以使用反射)函數

  • hasattr(object,name) 判斷object中有沒有一個name字符串對應的方法或屬性
  • getattr(object, name, default=None)
  • setattr(x, y, v)
  • delattr(x, y)
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()
反射的用途1
#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('其餘邏輯')
反射用途2:實現可插拔機制
#!/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()
相關文章
相關標籤/搜索