python3之模塊和面向?qū)ο?/h1>

一逼泣、模塊介紹

一個.py文件就是一個模塊,模塊中可以定義函數(shù)舟舒、類和變量拉庶。

  • 模塊包括:內(nèi)置模塊、三方模塊和自定義模塊秃励。
  • 模塊的優(yōu)點:
    提高代碼的可維護性
    提高代碼的復用性
    避免了函數(shù)名和變量名的沖突
    可以引用其他模塊

1. 引用模塊

  • import語句:
import 模塊1[, 模塊2..., 模塊n]
import 模塊名.函數(shù)名
import 模塊名.變量名
  • from...import...語句
from 模塊名 import 方法1[, 方法2, ...方法n]
從模塊中導入指定的方法到當前命名空間
from 模塊名 import *
把模塊中的所有內(nèi)容全部導入到當前命名空間
  • 導入模塊指定別名
from 模塊名 import 方法1 as name
從模塊中導入方法1并指定別名為name氏仗,調(diào)用時name.XXX或name(XXX)
  • 引用模塊的方法注意事項:
    同一模塊無論被import多少次,為了防止重復引入夺鲜,均只會被引入一次皆尔。
    可一次性引入多個模塊,不同模塊之間用逗號分隔

2. 模塊中特殊屬性

2.1. __name__屬性

模塊就是一個可執(zhí)行的.py文件币励,一個模塊被另一個程序引入慷蠕。
如果不想讓模塊中的某些代碼執(zhí)行,可以用__name__屬性食呻。每個模塊都有一個__name__屬性流炕。
當前文件如果為程序的入口文件時澎现,則__name__ == "__main__"。當__name__屬性的值為"__main__"時每辟,則表明該模塊自身在執(zhí)行剑辫;否則被引用其他文件。

3. 包

防止模塊命名沖突影兽,引入按目錄來組織模塊的方法揭斧,稱為包package。
引入包后峻堰,只要頂層的包與其他文件不沖突讹开,此包下的模塊就不會與其他文件發(fā)生沖突。
每個包下必須存在一個__init__.py文件捐名,此文件內(nèi)容可為空旦万。
__init__.py文件的作用:避免一些濫竽充數(shù)的名字,且目錄下只有存在此文件才可認為此目錄為一個包镶蹋。

4. 安裝第三方模塊

(1)前提:安裝python時安裝有pip
查看是否安裝有pip方法成艘,命令行輸入pip -V

C:\Users\admin>pip -V
pip 18.1 from d:\programs\python\python36\lib\site-packages\pip (python 3.6)

(2)安裝三方模塊

  • pip install 模塊名
    安裝模塊時有時會報錯,提示升級pip版本贺归。
  • pip install --upgrade pip:升級pip版本
(1)安裝Pillow模塊:
C:\Users\admin>pip install Pillow
Requirement already satisfied: Pillow in d:\programs\python\python36\lib\site-packages (5.3.0)
You are using pip version 18.1, however version 19.1.1 is available.
You should consider upgrading via the 'python -m pip install --upgrade pip' command.
---報錯淆两,提示升級pip
(2)升級pip
遇到過升級pip后無法找到pip模塊:
File "D:\Programs\Python\Python36\Scripts\pip.exe\__main__.py", line 5, in <module>
ModuleNotFoundError: No module named 'pip'。但實際上有pip文件拂酣。
解決方案:
首先執(zhí)行:python -m ensurepip
再升級pip:python -m pip install --upgrade pip

(3)查看pip安裝的模塊

  • pip list:列出所有的模塊信息
  • pip show -V 模塊名 | findstr Version:window下獲取某個模塊的版本號
  • pip show -V 模塊名 | grep Version:Linux下獲取某個模塊的版本號

二秋冰、面向?qū)ο?/h2>

1. 面向過程和面向?qū)ο蟮慕榻B

1.1. 面向過程:

  • 程序從上到下順序執(zhí)行的代碼 。
  • 面向過程強調(diào)的是功能行為

1.2. 函數(shù)式:

  • 將功能代碼封裝到函數(shù)中婶熬,無需重復編寫剑勾,僅調(diào)用函數(shù)。

1.3. 面向?qū)ο螅?/h4>
  • 把數(shù)據(jù)及對數(shù)據(jù)的操作方法放在一起赵颅,作為一個相互依賴的整體虽另,這就是對象。
  • 把對同類對象抽象出其共性饺谬,形成類捂刺。
    類中的大多數(shù)數(shù)據(jù),只能用本類的方法進行處理商蕴;
    類通過一個簡單的外部接口與外界發(fā)生聯(lián)系叠萍,對象與對象之間通過消息進行通信;
    程序流程由用戶在使用中決定绪商;
  • 面向?qū)ο笫腔诿嫦蜻^程的苛谷。
  • 面向?qū)ο笫菍⒐δ芊庋b成對象,強調(diào)的是具備功能的對象
  • 面向?qū)ο罂梢詫碗s的事情簡單化
  • 面向?qū)ο驩O(object-oriented)的三大特性:多態(tài)格郁、封裝腹殿、繼承独悴。

2. 類

2.1. 類的介紹

  • 類是用來描述事件的屬性和行為動作。
    屬性:對應(yīng)類中的成員變量锣尉;
    行為:對應(yīng)類中成員方法或功能刻炒;
    定義類就是定義類中的成員(成員變量和成員方法),擁有相同屬性和行為的對象都可以使用此類自沧。
    設(shè)計類包括:類名坟奥、屬性、行為(方法/功能)拇厢。

2.2. 創(chuàng)建類

  • 類是一種數(shù)據(jù)類型爱谁,本身并不占內(nèi)存空間。用類創(chuàng)建實例化對象(變量)孝偎,對象占內(nèi)存空間访敌。
  • 類以class 關(guān)鍵詞開頭,后接類名(類名通常是以大寫開頭的單詞)
  • 定義有繼承的類衣盾,則在類名后緊跟以括號括起來的父類名寺旺,表示該類是從此父類繼承下來的。一個類可以繼承多個類势决,類之間用逗號分隔阻塑。
    若無合適的繼承類,可使用object類(object類是所有類最終都會繼承的類果复。)---object類又稱基類和超類叮姑。
  • 類中定義的函數(shù),第一個參數(shù)永遠是self据悔,并且調(diào)用時不用傳遞該參數(shù)。self代表類的實例耘沼,即某個對象极颓。(注:沒有在類中定義的函數(shù),參數(shù)中無需添加變量self)
-----創(chuàng)建類的格式:
class 類名(父類1, 父類2...): 
   屬性
   行為

-----訪問類
1. 使用類實例化對象
實例化對象格式:對象名 = 類名(參數(shù)列表)
注:類沒有參數(shù)群嗤,類名后的小括號也不可省略菠隆。
2. 訪問屬性
訪問屬性格式:對象名.屬性名
賦新值:對象名.屬性名 = 新值
3. 訪問方法
訪問方法格式:對象名.方法名(參數(shù)列表)
# 創(chuàng)建不含繼承的類
class Student1:
    name = "zhangsan"       # 屬性

    def getScore(self, score):      # 方法
        print("這個學生的分數(shù)是:", score)

# 獲取類的實例化對象
student1 = Student1()
# 訪問屬性
getName = student1.name
print(getName)              # zhangsan
# 訪問方法
student1.getScore(90)       # 這個學生的分數(shù)是: 90
# 創(chuàng)建含繼承的類
class Student2(object):
    name = "zhangsan"       # 屬性

    def getScore(self, score):      # 方法
        print("這個學生的分數(shù)是:", score)

# 獲取類的實例化對象
student2 = Student2()
# 訪問屬性
getName = student2.name
print(getName)              # zhangsan
# 訪問方法
student2.getScore(80)       # 這個學生的分數(shù)是: 80

2.3. 構(gòu)造函數(shù)

  • 構(gòu)造函數(shù)__init__():即對象的初始化,使用類創(chuàng)建對象的時候自動調(diào)用狂秘。
-----創(chuàng)建類的格式:
class 類名(父類1, 父類2...): 
    def __init__(self, 屬性1, 屬性2,...):      # 屬性
        self.屬性1 = 屬性1      
        self.屬性2 = 屬性2
        ...
   def 方法函數(shù)(self, 方法參數(shù)1, 方法參數(shù)2, ...)
        行為

-----訪問類
1. 使用類實例化對象
實例化對象格式:對象名 = 類名(屬性參數(shù)列表)
注:類沒有參數(shù)骇径,類名后的小括號也不可省略。
2. 訪問屬性
訪問屬性格式:對象名.屬性名
賦新值:對象名.屬性名 = 新值
3. 訪問方法
訪問方法格式:對象名.方法名(方法參數(shù)列表)
# 創(chuàng)建含構(gòu)造函數(shù)的類
class Student3(object):
    def __init__(self, name):
        self.name = name

    def getScore(self, score):
        print("這個學生的分數(shù)是:", score)

# 獲取類的實例化對象
student3 = Student3("liNing")
# 訪問屬性
print(student3.name)        # liNing
# 訪問方法
student3.getScore("70")     # 這個學生的分數(shù)是: 70

2.4. self介紹

  • self代表類的實例者春,而非類破衔。
    哪個對象調(diào)用方法,那么該方法中的self就代表哪個對象钱烟。
    self不是python的關(guān)鍵字晰筛,將對象方法中的self換成其他標識符也可以嫡丙,但一般常規(guī)是用self。
1. -----類的內(nèi)部訪問屬性和方法-----
訪問屬性格式:self.屬性名
訪問方法格式:self.方法名(參數(shù))
獲取類名:self.__class__
2. -----類的外部訪問屬性和方法-----
訪問屬性格式:類的實例化對象.屬性名
訪問方法格式:類的實例化對象.方法(參數(shù))
"""類的內(nèi)部和外部分別獲取屬性和方法"""
class Student4(object):
    def __init__(self, name):
        self.name = name

    def getScore(self, score):
        return score

    def getStudentInfo(self, score):
        print("姓名:%s读第,分數(shù):%d" % (self.name, self.getScore(score)))       # 類的內(nèi)部訪問屬性和方法

    def getClassName(self):             # 獲取類名
        print(self.__class__)

    def createObject(self):             # 創(chuàng)建對象
        newObject = self.__class__("LiHong")
        print(newObject)

# 獲取類的實例化對象
student4 = Student4("LiMing")
# 類的外部訪問屬性
print(student4.name)                # LiMing
# 類的外部訪問方法
student4.getStudentInfo(80)         # 姓名:LiMing曙博,分數(shù):80
student4.getClassName()             # <class '__main__.Student4'>
student4.createObject()             # <__main__.Student4 object at 0x000000000234E240>

2.5. 析構(gòu)函數(shù)

  • 析構(gòu)函數(shù)__del__():釋放對象時自動調(diào)用,一般不需要手動添加析構(gòu)函數(shù)怜瞒。
    只有當對象的引用數(shù)為0時才會自動調(diào)用析構(gòu)函數(shù)來回收資源父泳。
    在函數(shù)中定義的對象,會在函數(shù)結(jié)束時自動釋放吴汪,以減小內(nèi)存空間的浪費惠窄。
    del 對象:手動刪除對象時會調(diào)用析構(gòu)函數(shù)。對象釋放后不可再訪問此對象浇坐。
  • 構(gòu)造函數(shù)和析構(gòu)函數(shù)的區(qū)別
    創(chuàng)建一個對象時一定會調(diào)用構(gòu)造函數(shù)睬捶;
    對象結(jié)束時一定會調(diào)用析構(gòu)函數(shù)。
class Student5(object):
    def __init__(self, name):
        self.name = name

    def getScore(self, score):
        return score

    def getStudentInfo(self, score):
        print("%s的分數(shù)是%d" % (self.name, self.getScore(score)))

    def __del__(self):
        print("這是個析構(gòu)函數(shù)")

student5 = Student5("LiMing")
print(student5.getScore(80))
student5.getStudentInfo(80)
# del student5                  # 刪除student5對象
# student5.getStudentInfo()     # 刪除student5對象后近刘,不可再使用此對象擒贸,否則會提示對象未被定義
print("代碼結(jié)束")
"""運行結(jié)果:
80
LiMing的分數(shù)是80
代碼結(jié)束
這是個析構(gòu)函數(shù)
"""

2.6. 類中特殊方法__str__()__repr__()

  • __str__():在調(diào)用print打印對象時自動調(diào)用,是給用戶使用的觉渴,是一個用來描述對象的方法介劫。
  • __repr__():在python解釋器中輸入對象名時,調(diào)用的方法案淋。
    注意:在沒有__str__座韵,但有__repr__時,調(diào)用print打印對象時會自動調(diào)用__repr__踢京。
    優(yōu)點:當一個對象的屬性值很多誉碴,并且都需要打印多次時,可將屬性信息添加到此方法中瓣距,簡化代碼黔帕。
    __str__()__repr__()方法使用任意一種即可,一般使用__str__()蹈丸。
class Student6(object):
    def __init__(self, name, sex, score):
        self.name = name
        self.sex = sex
        self.score = score

    def getStudentInfo(self):
        print("%s的分數(shù)是%d" % (self.name, self.score))

    def __str__(self):      # 這是個__str__函數(shù)
        return "name=%s, sex=%s, score=%d" % (self.name, self.sex, self.score)

    def __repr__(self):     # 這是個__repr__函數(shù)
        return "name=%s, sex=%s, score=%d" % (self.name, self.sex, self.score)

# 獲取類的實例化對象
student6 = Student6("LiMing", "female", 80)
# 打印對象
print(student6)         # name=LiMing, sex=female, score=80

2.7. 類中私有屬性

  • 在屬性前加兩個下劃線成黄,則表示該屬性為私有屬性。在類的外部不可使用或訪問私有屬性逻杖,但在類的內(nèi)部可以正常訪問奋岁。
  • 若在類的外部直接訪問私有屬性,python解釋器會把該私有屬性名變?yōu)?code>_類名__私有屬性名(即_Person1__money)荸百,且不同的解釋器將該私有屬性名修改的名字可能不同闻伶,故不允許使用類直接訪問私有屬性。-----私有屬性并不是絕對私有
  • 可通過自定義的方法修改私有屬性的值和獲取私有屬性的值-----類的外部間接訪問私有屬性管搪。
    私有屬性一般會通過添加set方法和get方法來訪問虾攻。
  • 在屬性前后均加兩個下劃線铡买,則該屬性并不是私有屬性,而是特殊變量霎箍,類內(nèi)外部均可直接訪問奇钞。
"""外部無法訪問私有屬性"""
class Person1(object):

    def __init__(self, name, sex, money):
        self.name = name
        self.sex = sex
        self.__money = money

    def getInfo(self):
        print("%s擁有%d錢" % (self.name, self.__money))        # 內(nèi)部可以使用私有屬性__money

person1 = Person1("LiMing", "female", 1000)
# print(person1.__money)       # 報錯,外部無法訪問私有屬性__money
# person1.__money = 100       # 外部也可以訪問此私有屬性漂坏,但此私有屬性名已發(fā)生改變景埃,故不允許此用法
"""外部修改和獲取私有屬性的方法"""
class Person2(object):
    def __init__(self, name, sex, money):
        self.name = name
        self.sex = sex
        self.__money = money

    def setMoney(self, money):      # 修改私有屬性的值
        if money < 0:
            money = 0
        self.__money = money

    def getMoney(self):             # 獲取私有屬性的值
        return self.__money

person2 = Person2("LiMing", "female", 1000)
print(person2.getMoney())           # 1000
person2.setMoney(200)              
print(person2.getMoney())           # 200

3. 面向?qū)ο蟮暮唵卫?/h3>
"""用例:人開車
分析:需要創(chuàng)建三個類,人顶别、車谷徙、油箱
人---類名:Person;屬性:car驯绎;方法:開車完慧、加油
車---類名:Car;屬性:油箱剩失;方法:車跑
油箱---類名:OilBox屈尼;屬性:油
"""
class OilBox(object):      
    """創(chuàng)建一個油箱"""
    def __init__(self, oil):
        self.oil = oil
class Car(object):
    """創(chuàng)建一個車"""
    def __init__(self, oilBox):
        self.oilBox = oilBox      # 油箱

    def run(self):
        """車執(zhí)行跑操作"""
        if self.oilBox.oil == 0:
            print("沒有油了")
        else:
            self.oilBox.oil -= 10
            print("剩余油量", self.oilBox.oil)
class Person(object):
    """創(chuàng)建一個人"""
    def __init__(self, car):
        self.car = car

    def driver(self):
        """人要開車, 車要跑"""
        self.car.run()

    def addOil(self, oil):
        """給車加油"""
        self.car.oilBox.oil = oil
"""使用面向?qū)ο髮崿F(xiàn)人開車操作"""
from Examples.Example1.person import Person
from Examples.Example1.car import Car
from Examples.Example1.oilBox import OilBox

oilBox = OilBox(100)    # 創(chuàng)建一個油箱對象
car = Car(oilBox)        # 創(chuàng)建一個車對象
person = Person(car)    # 創(chuàng)建一個人對象
person.driver()          # 人開車
person.addOil(200)    # 人加油
person.driver()

三拴孤、繼承

1. 繼承定義

  • 類A繼承類B脾歧,則繼承者(A)稱為子類(派生類),被繼承者(B)稱為父類(基類或超類)演熟。
    object類是所有類的父類(基類或超類)鞭执。
    子類可以直接使用父類中的屬性和方法,而不用重新編寫代碼芒粹;
    子類可以重新定義父類中的某個屬性和重寫某個方法兄纺,從而覆蓋父類中原有的屬性和方法;
    子類可以添加新的屬性和方法化漆。
  • 繼承的優(yōu)點:簡化代碼囤热,減小冗余;提高了代碼的健壯性和安全性获三。
  • 繼承的缺點:繼承的耦合性很高(因為父類發(fā)生改變,子類也會發(fā)生改變)锨苏。
    耦合性:模塊之間相互聯(lián)系的緊密程度疙教,越緊密耦合性越強;
    內(nèi)聚性:一個模塊內(nèi)部各個元素彼此結(jié)合的緊密程度伞租。
    耦合與內(nèi)聚是描述類與類之間的關(guān)系的贞谓,耦合性越低內(nèi)聚性越高,代碼越好葵诈。
  • 繼承分為:單繼承裸弦、多繼承祟同。

2. 單繼承

單繼承即僅繼承一個類。

2.1. 子類屬性的繼承和重寫

  • 子類中無構(gòu)造函數(shù)
    子類中若無構(gòu)造函數(shù)理疙,則子類也可直接使用父類的屬性晕城。
  • 子類中構(gòu)造函數(shù)的重寫
    父類中存在構(gòu)造函數(shù),子類中也有構(gòu)造函數(shù)窖贤,則子類的構(gòu)造函數(shù)需要調(diào)用父類的構(gòu)造函數(shù)砖顷。
    子類構(gòu)造函數(shù)中也可添加有新的屬性。
子類中構(gòu)造函數(shù)調(diào)用父類構(gòu)造函數(shù)有兩種方法:
第一種:父類.__init__(self, 參數(shù)1, 參數(shù)2, ...)
第二種:super(子類, self).__init__(參數(shù)1, 參數(shù)2, ...)

2.2. 子類方法的繼承和重寫

  • 子類中無與父類相同的方法赃梧,則子類可以直接使用父類的方法滤蝠。
  • 子類中存在與父類相同的方法,則子類的方法會覆蓋父類的方法授嘀。

2.3. 子類繼承單個父類的例子

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

    def eat(self, food):
        print("%s正在吃%s" % (self.name, food))
"""------子類使用父類的屬性和方法------"""
class Teacher1(Person):
    pass

# 子類使用父類的屬性
teacher1 = Teacher1("A", 20)
print(teacher1.name, teacher1.age)  # A 20
# 子類使用父類的方法
teacher1.eat("rice")                # A正在吃rice

"""------子類重寫父類的屬性物咳、直接使用父類的方法------"""
class Teacher2(Person):
    def __init__(self, name, age):
        """子類重寫父類屬性"""
        # Person.__init__(self, name, age)              # 重寫構(gòu)造函數(shù)的第一種方法
        super(Teacher2, self).__init__(name, age)       # 重寫構(gòu)造函數(shù)的第二種方法

# 子類使用父類的屬性
teacher2 = Teacher2("A", 20)
print(teacher2.name, teacher2.age)  # A 20
# 子類直接使用父類的方法
teacher2.eat("fish")                # A正在吃fish

"""------子類重寫父類屬性且添加新的屬性,子類重寫父類方法------"""
class Teacher3(Person):
    def __init__(self, name, age, sex):
        """子類重寫父類屬性"""
        # Person.__init__(self, name, age)              # 重寫構(gòu)造函數(shù)的第一種方法
        super(Teacher3, self).__init__(name, age)       # 重寫構(gòu)造函數(shù)的第二種方法
        self.sex = sex

    def eat(self, food):
        """子類重寫父類方法"""
        print("%s is eating %s" % (self.name, food))

teacher3 = Teacher3("A", 20, "female")
print(teacher3.name, teacher3.age, teacher3.sex)  # A 20 female
# 子類直接使用父類的方法
teacher3.eat("fish")            # A is eating fish

3. 多繼承

多繼承即同時繼承多個類蹄皱。

3.1. 子類屬性的繼承和重寫

  • 子類需要重寫父類的構(gòu)造函數(shù)览闰,且也可添加屬于自己的新屬性。
    子類構(gòu)造函數(shù)中也可添加有新的屬性夯接。
父類1.__init__(self, 參數(shù)1, 參數(shù)2, ...)
父類2.__init__(self, 參數(shù)1, 參數(shù)2, ...)
...
父類n.__init__(self, 參數(shù)1, 參數(shù)2, ...)

3.2. 子類方法的繼承和重寫

  • 子類繼承多個父類焕济,且父類中存在相同的方法名。
    若子類中未重寫此方法盔几,子類使用此方法時晴弃,默認調(diào)用的是括號中排在前面的父類方法;
    若子類中重寫有此方法逊拍,則會使用子類中的方法上鞠。

3.3. 子類繼承多個父類的例子

  • 子類Person既是程序員又是廚師
class Programmer(object):       # 程序員
    def __init__(self, language):
        self.language = language

    def writeCode(self):
        print("用%s語言寫代碼" % self.language)

    def phone(self):
        print("程序員在打電話")

class Chef(object):         # 廚師
    def __init__(self, food):
        self.food = food

    def cooking(self):
        print("烹飪%s" % self.food)

    def phone(self):
        print("廚師在打電話")
"""------子類繼承多個父類,子類重寫父類的屬性------"""
class Person1(Programmer, Chef):

    def __init__(self, name, age, language, food):
        """子類重寫父類屬性"""
        Programmer.__init__(self, language)
        Chef.__init__(self, food)
        self.name = name
        self.age = age

# 創(chuàng)建類的實例化對象
person1 = Person1("A", 18, "Python", "fish")
# 對象的屬性
print(person1.name, person1.age, person1.language, person1.food)    # A 18 Python fish
# 子類使用父類方法
person1.writeCode()         # 用Python語言寫代碼
person1.cooking()           # 烹飪fish
# 父類存在相同的方法芯丧,子類使用時默認使用括號中排名在前的方法
person1.phone()             # 程序員在打電話

"""------子類繼承多個父類芍阎,子類重寫父類的屬性且重寫父類方法------"""
class Person2(Programmer, Chef):

    def __init__(self, name, age, language, food):
        """子類重寫父類屬性"""
        Programmer.__init__(self, language)
        Chef.__init__(self, food)
        self.name = name
        self.age = age

    def phone(self):
        print("%s在打電話" % self.name)

person2 = Person2("A", 20, "Python", "fish")
person2.phone()         # A在打電話

四、多態(tài)

多態(tài):一種事件的多種形態(tài)缨恒。意味著即使不知道變量指向什么對象谴咸,也能夠?qū)Υ藢ο髨?zhí)行操作,且操作的行為跟隨對象所必的類型而變骗露。

class Animal(object):
    def __init__(self, name):
        self.name = name

    def run(self):
        print("%s在跑步" % self.name)

"""采用多態(tài)方式實現(xiàn)"""
class Person(object):
    def leadAnimalRun(self, animal):    # animal采用的多態(tài)方式
        print("人訓練動物跑步")
        animal.run()

person = Person()
cat = Animal("Cat")
person.leadAnimalRun(cat)
dog = Animal("Dog")
person.leadAnimalRun(dog)

五岭佳、對象屬性和類屬性

一個類所包含的屬性有:對象屬性和類屬性。

1. 類屬性

  • 在類中萧锉,方法外面定義的變量稱為類屬性珊随。
    在類的內(nèi)部和外部,類屬性值均可以通過類或?qū)ο髞碓L問,但只能通過類來修改叶洞。

1.1. 訪問類屬性

  • 通過類訪問類屬性
    在類的內(nèi)部和外部訪問:類名.類屬性
  • 通過對象訪問類屬性
    在類的內(nèi)部訪問:self.類屬性
    在類的外部訪問:實例化對象.類屬性

1.2. 修改類屬性

  • 類名.類屬性 = 新值
    通過類來修改類屬性值鲫凶,由于按全局變量的方式修改,則整個類中的此屬性值均發(fā)生變化衩辟。
  • self.類屬性 = 新值實例化對象.類屬性 = 新值
    此方法相當于把類屬性變成實例化對象屬性螟炫,相當于局部變量,僅會對當前對象生效惭婿,對此類創(chuàng)建的其他對象不生效不恭。

2. 對象屬性

  • 在類中,__init()__方法中定義的屬性稱為對象屬性财饥。
    在類的內(nèi)部訪問:self.對象屬性
    在類的內(nèi)部修改值:self.對象屬性 = 新值
    在類的外部訪問:實例化對象.對象屬性
    在類的外部修改值:實例化對象.對象屬性 = 新值
  • 可動態(tài)的給對象添加新的對象屬性换吧,但此對象只對當前對象生效,對此類創(chuàng)建的其他對象無用钥星。
  • 在同一類中沾瓦,若類屬性名與對象屬性名相同,則對象屬性的優(yōu)先級高于類屬性谦炒。
class Person1(object):
    count = 0                   # 類屬性

    def __init__(self, name):   # 對象屬性
        self.name = name

    def testClassAttribute(self):
        """通過類修改類屬性值"""
        Person1.count = 50  # 通過類名的方式給類屬性值賦新值贯莺,相當于全局變量
        print(Person1.count)  # 50
        print(self.count)  # 50
        """通過對象修改類屬性值"""
        self.count = 60  # 通過對象的方式給類屬性值賦新值,相當于局部變量宁改,僅對當前對象生效
        print(Person1.count)  # 50
        print(self.count)  # 60

    def testObjectAttribute(self):
        """對象屬性"""
        self.name = 'B'
        print(self.name)    # B

person1 = Person1("A")
person1.testClassAttribute()
print(Person1.count)        # 50
print(person1.count)        # 60

person1.testObjectAttribute()
person1.name = "C"          # 類外部修改對象屬性值
person1.age = 20            # 類外部新建新的屬性缕探,并賦值
print(person1.name, person1.age)         # C 20

六、動態(tài)給實例添加屬性和方法

1. 動態(tài)給實例添加屬性和方法

  • 動態(tài)給實例添加屬性
    實例對象.新屬性 = 屬性值
  • 動態(tài)給實例添加方法
    先導入模塊from types import MethodType
    實例對象.新方法 = MethodType(方法名, 實例對象)
class Person(object):
    pass

person = Person()
"""給對象動態(tài)添加屬性"""
person.name = "LiMing"
print(person.name)      # LiMing
"""給對象動態(tài)添加方法"""
from types import MethodType    
def getAge(self, age):
    print("%s的年齡:%d" % (self.name, age))
person.ageMethod = MethodType(getAge, person)
person.ageMethod(20)            # LiMing的年齡:20

2. 限制對象中添加的動態(tài)屬性

定義類時定義一個特殊的屬性__slots__还蹲,此屬性可限制動態(tài)添加的屬性爹耗。

from types import MethodType    
class Student:
    __slots__ = ("name", "age", "sex", "scoreInfo")      # 表示給Student類添加屬性時僅可添加name、age谜喊、sex潭兽、scoreInfo

student = Student()
student.name = "LiHong"
print(student.name)             # LiHong
# student.work = "Doctor"       # 會報錯提示此對象無work屬性
# print(student.work)
def getScore(self, score):
    print("%s的分數(shù):%d" % (self.name, score))
student.scoreInfo = MethodType(getScore, student)
student.scoreInfo(90)           # LiHong的分數(shù):90

七、運算符重載

對兩個對象執(zhí)行運算操作斗遏,則提示類型不支持(TypeError: unsupported operand type(s))山卦,因此需要借助運算符重載。

1. 常用的運算符重載

構(gòu)造函數(shù)__init__
解析函數(shù)__del__
打印函數(shù)__repr__诵次、__str__
函數(shù)調(diào)用__call__
函數(shù)屬性__getattr__账蓉、__setattr__、__delattr__
數(shù)字運算符函數(shù):__add__(self, other)逾一、__sub__(self, other)剔猿、__mul__(self, other)、__div__(self, other)
...
class Student:
    def __init__(self, score):
        self.score = score

    def __add__(self, other):
        return Student(self.score + other.score)

    def __str__(self):
        return "score=%d" % self.score

student1 = Student(70)
student2 = Student(80)
print(student1 + student2)                  # score=150
print(student1.__add__(student2).score)     # 150

2. __call__介紹:

__call__是一個可調(diào)用對象嬉荆,而函數(shù)和類都屬于可調(diào)用對象。
通過__call__方法可以將一個類實例化對象變成一個可調(diào)用對象酷含。使用__call__還可以

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

    def __call__(self, name, sex):
        self.name = name
        self.sex = sex

person = Person("LiMing", 20, "female")     # 實例化對象
person("LiHong", "male")                    # 將實例變?yōu)榭烧{(diào)用的對象
print(person.name, person.sex, person.age)      # LiHong male 20
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者

  • 序言:七十年代末鄙早,一起剝皮案震驚了整個濱河市汪茧,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌限番,老刑警劉巖舱污,帶你破解...
    沈念sama閱讀 218,682評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異弥虐,居然都是意外死亡扩灯,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,277評論 3 395
  • 文/潘曉璐 我一進店門霜瘪,熙熙樓的掌柜王于貴愁眉苦臉地迎上來珠插,“玉大人,你說我怎么就攤上這事颖对∧沓牛” “怎么了?”我有些...
    開封第一講書人閱讀 165,083評論 0 355
  • 文/不壞的土叔 我叫張陵缤底,是天一觀的道長顾患。 經(jīng)常有香客問我,道長个唧,這世上最難降的妖魔是什么江解? 我笑而不...
    開封第一講書人閱讀 58,763評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮徙歼,結(jié)果婚禮上犁河,老公的妹妹穿的比我還像新娘。我一直安慰自己鲁沥,他們只是感情好呼股,可當我...
    茶點故事閱讀 67,785評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著画恰,像睡著了一般彭谁。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上允扇,一...
    開封第一講書人閱讀 51,624評論 1 305
  • 那天缠局,我揣著相機與錄音,去河邊找鬼考润。 笑死狭园,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的糊治。 我是一名探鬼主播唱矛,決...
    沈念sama閱讀 40,358評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了绎谦?” 一聲冷哼從身側(cè)響起管闷,我...
    開封第一講書人閱讀 39,261評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎窃肠,沒想到半個月后包个,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,722評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡冤留,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年碧囊,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片纤怒。...
    茶點故事閱讀 40,030評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡糯而,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出肪跋,到底是詐尸還是另有隱情歧蒋,我是刑警寧澤,帶...
    沈念sama閱讀 35,737評論 5 346
  • 正文 年R本政府宣布州既,位于F島的核電站谜洽,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏吴叶。R本人自食惡果不足惜阐虚,卻給世界環(huán)境...
    茶點故事閱讀 41,360評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望蚌卤。 院中可真熱鬧实束,春花似錦、人聲如沸逊彭。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,941評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽侮叮。三九已至避矢,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間囊榜,已是汗流浹背审胸。 一陣腳步聲響...
    開封第一講書人閱讀 33,057評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留卸勺,地道東北人砂沛。 一個月前我還...
    沈念sama閱讀 48,237評論 3 371
  • 正文 我出身青樓,卻偏偏與公主長得像曙求,于是被迫代替她去往敵國和親碍庵。 傳聞我的和親對象是個殘疾皇子映企,可洞房花燭夜當晚...
    茶點故事閱讀 44,976評論 2 355

推薦閱讀更多精彩內(nèi)容