Python 面向?qū)ο?/h2>

面向過程的思想與面向?qū)ο蟮乃枷?/h3>
  1. 面向過程的思維:當(dāng)你拿到一個(gè)問題,你分析這個(gè)問題是第一步先做什么,第二步再做什么
  2. 面向?qū)ο蟮乃季S:你應(yīng)該分析這個(gè)問題里面有哪些類和對象,再分析這些類和對象應(yīng)該具有哪些屬性和方法,最后分析類和類之間具體有什么關(guān)系

面向?qū)ο蟮脑O(shè)計(jì)思想

  1. 面向?qū)ο蟮幕舅枷胧?,從現(xiàn)實(shí)世界中客觀存在的事物出發(fā)來構(gòu)造軟件系統(tǒng),并在系統(tǒng)的構(gòu)造中盡可能運(yùn)用人類的自然思維方式。
  2. 面向?qū)ο蟾訌?qiáng)調(diào)運(yùn)用人類在日常生活的邏輯思維中經(jīng)常采用的思想方法與原則,如抽象、分類,繼承、聚合、多態(tài)等。

對象和類的概念

  1. 對象是用于計(jì)算機(jī)語言對問題域中事物的描述,對象通過“屬性(attribute)”和“方法(method)”來分別對應(yīng)事物所具有的靜態(tài)屬性和動態(tài)屬性。
  2. 類是用于描述同一類的對象的一個(gè)抽象的概念,類中定義了這一類對象所具有的靜態(tài)屬性和動態(tài)屬性
oop-intro.png

Python面向?qū)ο?/h3>

創(chuàng)建類

  1. 使用 class 語句來創(chuàng)建一個(gè)新類,class 之后為類的名稱并以冒號結(jié)尾
  2. Python類中的方法與普通的函數(shù)只有一個(gè)特別的區(qū)別——它們必須有一個(gè)額外的第一個(gè)參數(shù)名稱, 按照慣例它的名稱是 self,其中self代表的是類的實(shí)例,即當(dāng)前對象
class Person(object):
    """This class is designed to describe a person
    
    Detail information

    :param sex: user sex, man or woman
    :param age: user age
    """
    
    def __init__(self, sex, age):
        self.sex = sex
        self.age = age

    def user_age(self):
        return self.age
    
    @staticmethod 
    def desc():
        return Person.__doc__

創(chuàng)建實(shí)例對象

實(shí)例化類其他編程語言中一般用關(guān)鍵字 new,但是在 Python 中并沒有這個(gè)關(guān)鍵字,類的實(shí)例化類似函數(shù)調(diào)用方式。
以下使用類的名稱 Person來實(shí)例化,并通過 init 方法接收參數(shù)

person1 = Person("man", 20)
person2 = Person("woman", 19)

訪問屬性

通常使用點(diǎn)號 . 來訪問對象的屬性。使用如下類的名稱訪問類變量:

person1 = Person("man", 20)

person1.age
person1.sex

屬性的高級訪問方法

  1. getattr(obj, name[, default]) : 訪問對象的屬性。
  2. hasattr(obj,name) : 檢查是否存在一個(gè)屬性。
  3. setattr(obj,name,value) : 設(shè)置一個(gè)屬性。如果屬性不存在,會創(chuàng)建一個(gè)新屬性。
  4. delattr(obj, name) : 刪除屬性。

類的內(nèi)置屬性(僅Python)

  1. _dict_: 類的屬性 (包含一個(gè)字典,由類的數(shù)據(jù)屬性組成)
  2. _doc_: 類的文檔字符串
  3. _name_: 類名
  4. _module_: 類定義所在的模塊(類的全名是'_main_.className',如果類位于一個(gè)導(dǎo)入模塊mymod中,那么className._module_ 等于 mymod)
  5. _bases_ : 類的所有父類構(gòu)成元素(包含了一個(gè)由所有父類組成的元組)
  6. 析構(gòu)函數(shù) _del_ ,_del_在對象銷毀的時(shí)候被調(diào)用,當(dāng)對象不再被使用時(shí)

property屬性

property是一種特殊的屬性,訪問它時(shí)會執(zhí)行一段功能(函數(shù))然后返回值。將一個(gè)類的函數(shù)定義成特性以后,對象再去使用的時(shí)候obj.name,根本無法察覺自己的name是執(zhí)行了一個(gè)函數(shù)然后計(jì)算出來的

注意:此時(shí)的特性arear不能被賦值

 import math
 class Circle:
     def __init__(self,radius): #圓的半徑radius
         self.radius=radius
 
     @property
     def area(self):
         return math.pi * self.radius**2 #計(jì)算面積

    @area.setter
    def area(self,value):
         self.__NAME=value #通過類型檢查后,將值value存放到真實(shí)的位置self.__NAME

    @area.getter
    def area():
        return self.radius

staticemethod方法

通常情況下,在類中定義的所有函數(shù)都是對象的綁定方法,對象在調(diào)用綁定方法時(shí)會自動將自己作為參數(shù)傳遞給方法的第一個(gè)參數(shù)。除此之外還有兩種常見的方法:靜態(tài)方法和類方法,二者是為類量身定制的,但是實(shí)例非要使用,也不會報(bào)錯(cuò)。

靜態(tài)方法是一種普通函數(shù),位于類定義的命名空間中,不會對任何實(shí)例類型進(jìn)行操作,python為我們內(nèi)置了函數(shù)staticmethod來把類中的函數(shù)定義成靜態(tài)方法

應(yīng)用場景: 編寫類時(shí)需要采用很多不同的方式來創(chuàng)建實(shí)例,而我們只有一個(gè)init函數(shù),此時(shí)靜態(tài)方法就派上用場了

class Date:
    def __init__(self,year,month,day):
        self.year=year
        self.month=month
        self.day=day
        
    @staticmethod
    def now():                                     # 用Date.now()的形式去產(chǎn)生實(shí)例,該實(shí)例用的是當(dāng)前時(shí)間
        t=time.localtime()                         # 獲取結(jié)構(gòu)化的時(shí)間格式
        return Date(t.tm_year,t.tm_mon,t.tm_mday)  # 新建實(shí)例并且返回
        
    @staticmethod
    def tomorrow():                                # 用Date.tomorrow()的形式去產(chǎn)生實(shí)例,
        t=time.localtime(time.time()+86400)
        return Date(t.tm_year,t.tm_mon,t.tm_mday)

classmethod類方法

類方法是給類用的,類在使用時(shí)會將類本身當(dāng)做參數(shù)傳給類方法的第一個(gè)參數(shù),python為我們內(nèi)置了函數(shù)classmethod來把類中的函數(shù)定義成類方法

class Person(object):
    
    count = 1
    
    @classmethod
    def test(cls):
        print(cls, cls.count)

注意注意注意:靜態(tài)方法和類方法雖然是給類準(zhǔn)備的,但是如果實(shí)例去用,也是可以用的,只不過實(shí)例去調(diào)用的時(shí)候容易讓人混淆,不知道你要干啥

類的繼承

通過繼承創(chuàng)建的新類稱為子類或派生類,被繼承的類稱為基類、父類或超類。
在python中繼承中的一些特點(diǎn):

  1. 如果在子類中需要父類的構(gòu)造方法就需要顯示的調(diào)用父類的構(gòu)造方法,或者不重寫父類的構(gòu)造方法。詳細(xì)說明可查看:python 子類繼承父類構(gòu)造函數(shù)說明。
  2. 在調(diào)用基類的方法時(shí),需要加上基類的類名前綴,且需要帶上 self 參數(shù)變量。區(qū)別在于類中調(diào)用普通函數(shù)時(shí)并不需要帶上 self 參數(shù)
  3. Python 總是首先查找對應(yīng)類型的方法,如果它不能在派生類中找到對應(yīng)的方法,它才開始到基類中逐個(gè)查找。(先在本類中查找調(diào)用的方法,找不到才去基類中找)。
class Parent(object):        
  
   parent_attr = 100
      
   def __init__(self):
      print "調(diào)用父類構(gòu)造函數(shù)"
 
   def parent_method(self):
      print '調(diào)用父類方法'
 
   def set_attr(self, attr):
      Parent.parent_attr = attr
 
   def get_attr(self):
      print "父類屬性 :", Parent.parent_attr
 
class Child(Parent): # 定義子類
   def __init__(self):
      print "調(diào)用子類構(gòu)造方法"
 
   def child_method(self):
      print '調(diào)用子類方法'

c = Child()          # 實(shí)例化子類
c.child_method()      # 調(diào)用子類的方法
c.parent_method()     # 調(diào)用父類方法
c.set_attr(200)       # 再次調(diào)用父類的方法 - 設(shè)置屬性值
c.get_attr()          # 再次調(diào)用父類的方法 - 獲取屬性值

多重繼承

如果在繼承元組中列了一個(gè)以上的類,那么它就被稱作"多重繼承" 。

class Child(Parent, Student):   
    pass

重載構(gòu)造方法

如果子類和父類都有構(gòu)造函數(shù),子類其實(shí)是重寫了父類的構(gòu)造函數(shù),如果不顯式調(diào)用父類構(gòu)造函數(shù),父類的構(gòu)造函數(shù)就不會被執(zhí)行
為了達(dá)到預(yù)期的效果,子類的構(gòu)造方法必須調(diào)用其父類的構(gòu)造方法來進(jìn)行基本的初始化


class Person(object):
    
    def __init__(self, sex, age):
        self.sex = sex
        self.age = age

class Student(Person):
    
    # 方法一
    def __init__(self, sex, age, school):
        Person.__init__(self, sex, age)
        self.school = school


class Student(Person):
    
    # 方法二
    def __init__(self, sex, age, school):
        super(Student, self).__init__(sex, age)
        self.school = school
    

特點(diǎn): 方法一更直觀,方法二可以一次初始化所有超類
小結(jié):https://blog.csdn.net/seizef/article/details/5310107

  1. super并不是一個(gè)函數(shù),是一個(gè)類名,形如super(B, self)事實(shí)上調(diào)用了super類的初始化函數(shù), 產(chǎn)生了一個(gè)super對象;
  2. super類的初始化函數(shù)并沒有做什么特殊的操作,只是簡單記錄了類類型和具體實(shí)例;
  3. super(B, self).func的調(diào)用并不是用于調(diào)用當(dāng)前類的父類的func函數(shù);
  4. Python的多繼承類是通過MRO(Method Resolution Order)的方式來保證各個(gè)父類的函數(shù)被逐一調(diào)用,而且保證每個(gè)父類函數(shù)只調(diào)用一次(如果每個(gè)類都使用super);
  5. 混用super類和非綁定的函數(shù)是一個(gè)危險(xiǎn)行為,這可能導(dǎo)致應(yīng)該調(diào)用的父類函數(shù)沒有調(diào)用或者一 個(gè)父類函數(shù)被調(diào)用多次。

類屬性與方法

  1. 類的私有屬性
    __private_attrs: 兩個(gè)下劃線開頭,聲明該屬性為私有,不能在類的外部被使用或直接訪問。在類內(nèi)部的方法中使用時(shí) self.__private_attrs

  2. 類的方法
    在類的內(nèi)部,使用 def 關(guān)鍵字可以為類定義一個(gè)方法,與一般函數(shù)定義不同,類方法必須包含參數(shù) self,且為第一個(gè)參數(shù)

  3. 類的私有方法
    __private_method:兩個(gè)下劃線開頭,聲明該方法為私有方法,不能在類的外部調(diào)用。在類的內(nèi)部調(diào)用 self.__private_methods

實(shí)例屬性和類屬性

當(dāng)我們定義了一個(gè)類屬性后,這個(gè)屬性雖然歸類所有,但類的所有實(shí)例都可以訪問到

class Student(object):
    name = "Student"

>>> s = Student()       # 創(chuàng)建實(shí)例
>>> print(s.name)       # 打印name屬性,因?yàn)閷?shí)例并沒有name屬性,所以會繼續(xù)查找class的name屬性
Student
>>> print(Student.name) # 打印類的name屬性
Student
>>> s.name = "ZhangSan" # 給實(shí)例綁定name屬性
>>> print(s.name)       # 由于實(shí)例屬性優(yōu)先級比類屬性高,因此,它會屏蔽掉類的name屬性
Zhangsan
>>> print(Student.name) # 但是類屬性并未消失,用Student.name仍然可以訪問
Student
>>> del s               # 如果刪除實(shí)例的name屬性
>>> print(s.name)       # 再次調(diào)用s.name,由于實(shí)例的name屬性沒有找到,類的name屬性就顯示出來了
Student

總結(jié):在實(shí)例中訪問一個(gè)屬性,但是實(shí)例中沒有,就試圖去類中尋找這個(gè)屬性。找到了,就有,沒找到,就拋出異常。當(dāng)試圖用實(shí)例去修改一個(gè)在類中不可變的屬性的時(shí)候,實(shí)際上并沒有修改,而是在實(shí)例中創(chuàng)建了這個(gè)屬性。當(dāng)再次訪問這個(gè)屬性時(shí),就不用去類中尋找了

單下劃線、雙下劃線、頭尾雙下劃線說明

  1. _foo_ : 定義的是特殊方法,一般是系統(tǒng)定義名字 ,類似 init() 之類的。
  2. _foo: 以單下劃線開頭的表示的是 protected 類型的變量,即保護(hù)類型只能允許其本身與子類進(jìn)行訪問,不能用于 from module import *
  3. __foo: 雙下劃線的表示的是私有類型(private)的變量, 只能是允許這個(gè)類本身進(jìn)行訪問了。

class Response(object):
    """The :class:`Response <Response>` object, which contains a
    server's response to an HTTP request.
    """

    __attrs__ = [
        '_content', 'status_code', 'headers', 'url', 'history',
        'encoding', 'reason', 'cookies', 'elapsed', 'request'
    ]

    def __init__(self):
        self._content = False
        self._content_consumed = False
        self._next = None

     @property
    def is_redirect(self):
        """True if this Response is a well-formed HTTP redirect that could have
        been processed automatically (by :meth:`Session.resolve_redirects`).
        """
        return ('location' in self.headers and self.status_code in REDIRECT_STATI)

    def close(self):
        """Releases the connection back to the pool. Once this method has been
        called the underlying ``raw`` object must not be accessed again.

        *Note: Should not normally need to be called explicitly.*
        """
        pass
  
  class JsonResponse(Response):
      
      @staticmethod
      def to_json():
          """Releases the connection back to the pool. 
          Once this method has been called the underlying ``raw`` object must not be accessed again.
          *Note: Should not normally need to be called explicitly.*
          """
          return xxx
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容