python-面向對象1

# 類(Class):用來描述具有相同屬性和方法的對象集合,它定義了該集合每個對象共有的屬性和方法,對象則是類的實例
# 類變量:類變量在整個實例化對象中是公用的。類變量定義在類中但是在函數體外。類變量通常不作爲實例變量使用。
# 實例變量:定義在方法中的變量,只作用於當前實例的類
# 數據成員:類變量或者實例變量都是,用於處理類及實例對象的相關數據
# 方法:類定義的函數
# 繼承:一個派生類也稱子類(derived class)繼承基類也稱父類(base class)的字段和方法。python中每個類都默認繼承object
# 方法重寫:如果父類的方法無法滿足字類的需求,可以對其改寫
# 實例化:創建類的實例,類的具體對象

1.創建類

# 定義一個類
class Occupation():
    Salary = 18000   # 類變量
    Satisfaction = 'NO'
    def __init__(self, post):   # 構造方法
        self.post = post     # 實例變量
    # 定義一個方法
    def policemenSalary(self):
        print('{}的薪資是:{},是否滿意當前薪資{}'.format(self.post, self.Salary, self.Satisfaction))

    def behavior(self):
        print('沒有崗位我什麼也不會做')

2.創建類的實例

# 創建Occupation類的實例p
o = Occupation('jc')
o.Satisfaction = 'YES'
o.policemenSalary()  # jc的薪資是:18000,是否滿意當前薪資YES
o.behavior()  # 執行結果:輸出  沒有崗位我什麼也不會做
# 創建Occupation類的實例p1
o1 = Occupation('gcs')
o1.policemenSalary()  # gcs的薪資是:18000,是否滿意當前薪資NO
o.behavior()  # 執行結果:輸出  沒有崗位我什麼也不會做

3.繼承

# 創建一個警察類繼承前面的職業類
class Policemen(Occupation):
    Satisfaction = 'YEN'
    # 重寫behavior方法
    def behavior(self):
        print('我是{},保護人民安全'.format(self.post))
# 創建Policemen類的實例
p = Policemen('警察')  # 因爲子類默認繼承父類的構造方法,所以子類實例化的時候也要傳遞參數
p.policemenSalary()  # 執行結果:輸出  警察的薪資是:18000,是否滿意當前薪資YEN
p.behavior()  # 執行結果:輸出  我是警察,保護人民安全

# 對象屬性和類的屬性
# 使用對象創建的屬性,只有當前對象存在該屬性,稱爲對象屬性
# 使用類創建的屬性,在每個對象裏都會存在,稱爲類屬性   比如上面的 Salary = 18000 每個對象裏面都可以訪問到
# 當在對象裏去修改類屬性值的時候,相當於在當前對象裏新創建一個對象屬性,當調用的時候優先調用對象的屬性,但是類本身的值,不會改變  比如上面的 o.Satisfaction = 'YES'
# 對象的屬性優先於類的屬性
# 避免對象屬性和類屬性重名, 因爲對象屬性會屏蔽掉類屬性,如果刪除對象屬性,會繼續使用類屬性

# 實例綁定屬性兩種方式
# 第一種是使用構造方法,在實例化的時候綁定
# 第二種是賦值   o.post = 'cxy'

4.類綁定屬性的操作

class Area():
    pass
# 給類綁定屬性
Area.numbering = '0771'
a = Area()
print(a.numbering) # 輸出結果  0771
a.numbering = '0775'  # 相當於給對象a綁定了numbering屬性,但是不會對類屬性產生影響0775這個值只有a可以訪問
# 給類設置屬性
setattr(Area,'attractions','青秀山')
print(a.attractions)  # 輸出結果  青秀山
# 查看類是否有某個屬性
print(hasattr(Area, 'numbering'),hasattr(Area, 'age'))  # 輸出結果,True False
# 獲取屬性
print(getattr(Area, 'numbering'))
# 輸出結果  0771
# 獲取屬性值,如果不存在返回一個默認值
print(getattr(Area, 'age','404'))  # 輸出結果 404

5.對象和類綁定方法的操作

class City():
    pass
def selfIntroduction(self, name):
    self.name = name
    print('我是{}'.format(self.name))
# 對象綁定方法
from types import MethodType
c = City()
c.selfIntroduction = MethodType(selfIntroduction, c)
c.selfIntroduction('南寧')  # 執行結果:輸出  我是南寧
print(c.name)  # 輸出結果:南寧
# 實例綁定的方法,對另外一個實例不起作用,所以別的實例不能訪問調用

def features(self,description):
    self.description = description
    print(self.description)

# 類綁定方法
City.features = MethodType(features,City)
c.features('開放包容')  # 執行結果: 輸出 開放包容
print(c.description)  # 輸出結果:開放包容
c1 = City();
c1.features('開拓創新')  # 執行結果:輸出 開拓創新
print(c1.description)  # 執行結果:輸出 開拓創新
# 給類綁定方法後,所有實例均可調用,而且綁定屬性是公共屬性,所有對象都可以對其修改

6.使用__slots__限制類實例添加屬性

class Student():
    __slots__ = ['name', 'age', 'grade']  # 實例只能綁定這幾個對象,但是類不受限制
Student.sex = '男'
print(Student.sex) # 輸出結果
# s = Student()
# s.sex1 = '女'  # 報錯 AttributeError: 'Student' object has no attribute 'sex1'
# 使用__slots__要注意,__slots__定義屬性僅對當前類起作用,對繼承的子類不起作用,多個屬性名可以用元組,集合,列表形式表達

7.私有屬性和私有方法

# 兩個下劃線開頭,聲明該屬性私有,不能在類外部被使用或者訪問。如果是在類內部調用,使用self.屬性名
class Animal():
    __category = '爬行'   # 私有屬性
    # 通過公共方法返回私有屬性
    def public_category(self):
        return self.__category
    def update_category(self,__category):
        self.__category = __category
a = Animal()
# 訪問私有屬性
# print(a.__category)  # 報錯 AttributeError: 'Animal' object has no attribute '__category'
print(a._Animal__category)  # 輸出結果:爬行
print(a.public_category())  # 執行結果:輸出 爬行
# 修改私有屬性
a.update_category('兩棲')
print(a.public_category())  # 輸出結果:兩棲
# 外部插入的私有屬性並不是真正的私有屬性
a.__exerciseMethod = '爬'
print(a.__exerciseMethod)  # 輸出結果:爬  和普通的綁定屬性並沒有上面卻別

# 在類內部修改類外部的屬性
class Animal():
    def update_exerciseMethod(self, __exerciseMethod):
        self.__dict__["__exerciseMethod"] = __exerciseMethod
a = Animal()
a.__exerciseMethod = '爬'
a.update_exerciseMethod('遊')
print(a.__exerciseMethod)  # 輸出結果:遊

# 私有方法
class Animal():
    def __privateFun(self):
        print('私有方法__privateFun')
        return '私有方法返回值'
    def publicPrivateFun(self):
        return self.__privateFun()
# 調用私有方法
a = Animal()
# 通過解析器方法調用
a._Animal__privateFun()   # 調用成功
# 通過類+實體
Animal._Animal__privateFun(Animal())  # 調用成功
# 通過公用方法調用
print(a.publicPrivateFun())  # 執行成功 輸出:私有方法返回值

# 子類調用父類的私有方法
class Tiger(Animal):
    def transferFatherPrivateFun(self):
        return self._Animal__privateFun()
t = Tiger()
t.transferFatherPrivateFun()  # 調用成功
t.publicPrivateFun()  # 調用成功

# 通過裝飾器訪問私有屬性
class Animal():
    __exerciseMethod = '飛行'
    @property
    def exerciseMethod(self):
        return self.__exerciseMethod
    @exerciseMethod.setter
    def exerciseMethod(self,exerciseMethod):
        self.__exerciseMethod = exerciseMethod
    def __fun(self):
        print('私有方法')
a = Animal()
print(a.exerciseMethod)  # 輸出結果  飛行
a.exerciseMethod = '爬行'
print(a.exerciseMethod)  # 輸出結果  爬行

8.多繼承

# 多繼承
class FatherClass0():
    pass
class FatherClass1(FatherClass0):
    pass
class FatherClass2(FatherClass1):
    pass
class FatherClass3(FatherClass0):
    pass
class SubClass(FatherClass2, FatherClass3):
    pass

s = SubClass()
# 查看查找順序
print(SubClass.mro())
# 輸出結果  [<class '__main__.SubClass'>, <class '__main__.FatherClass2'>, <class '__main__.FatherClass1'>,
# <class '__main__.FatherClass3'>, <class '__main__.FatherClass0'>, <class 'object'>]

多繼承查找順序

# 如果繼承的父類重寫了構造函數 __init__(self)  子類沒有重寫,
# 實例化時按照父類的的構造函數要求實例化,繼承多個父類時,優先調用重寫了構造函數的父類
class A (object):
    pass
class B(object):
    def __init__(self,i):
        pass
class C(A, B):
    pass
c = C(5)  # 實例化C的時候要按照B的構造函數要求傳遞參數,如果A也重寫了構造函數,則要按照A的要求

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章