Python——面向對象思想編程(二)

繼承

單繼承

有兩個類,A類和B類,當我們說A類繼承至B類的時候,那麼A類就擁有了B類中的所有的屬性和方法。
注意:繼承者稱爲子類,被繼承者稱爲父類。
繼承的作用:

  1. 簡化了代碼,減少冗餘。
  2. 提高了代碼的健壯性。
  3. 提高了代碼的安全性。
  4. 是多態的前提。

缺點:
耦合和內聚是描述類與類之間的關係的。耦合性越低,內聚性越高,代碼越好。

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

    # 通過內部的方法,去修改私有屬性
    def setWeight(self, weight):
        # 數據的過濾,這個其實可以更完善一些
        if weight < 0:
            weight = 0
        self.__weight = weight

    def getWeight(self):
        return self.__weight


# 我們在這裏定義一個子類,學生類,學生類繼承自Person類
class Student(Person):
    def __init__(self, name, age, weight):
    	# 調用父類中的__init__
        super().__init__(name, age, weight)


student = Student("tom", 18, 180)
print(student.getWeight())

運行結果:

180

可以看出,Student類繼承類Person類之後,就擁有了Person類的所有屬性和方法
以前的版本的super的寫法是

super(Student, self).__init__(name, age, weight)

這也是最標準的寫法,但是現在的python更爲先進了

super().__init__(name, age, weight)

括號裏面不寫也可以了,解釋器會自動幫我們識別

多繼承
class Father(object):
    def __init__(self, money):
        self.money = money

    def play(self):
        print('play')


class Mother(object):
    def __init__(self, eat):
        self.eat = eat

    def eatt(self):
        print('eatt')


class Child(Father, Mother):
    def __init__(self, money, eat):
        Father.__init__(self, money)
        Mother.__init__(self, eat)

c = Child(110, 'food')
c.play()

運行結果:

play

如果兩個父類的方法的方法名重複了,會從左到右按照順序調用父類的方法
按照我們的方法名來看的話,會調用Father的方法

對象屬性與類屬性

類屬性:

class Person(object):
   # 這裏的屬性實際上屬於類屬性(用類名來調用)
   name = 'person'


print(Person.name)

運行結果:

person

對象屬性:

class Person(object):
    # 這裏的屬性實際上屬於類屬性(用類名來調用)
    name = 'person'
    def __init__(self, name):
        pass
        # 對象屬性
        self.name = name


print(Person.name)
a = Person('tom')
# 對象屬性的優先級高於類屬性
print(a.name)
print(Person.name)

運行結果:

person
tom
person

也可以動態的給對象添加對象屬性:

a.age = 18

只針對於當前對象生效,對於類創建的其他對象沒有作用。
刪除對象中的類name屬性在調用會使用到同名的類屬性:

del a.name
print(a.name)

運行結果:

person

注意:以後千萬不要將對象屬性與類屬性重名,因爲對象屬性會屏蔽掉類屬性,但是當刪除對象屬性後,在使用又能使用到類屬性了。

動態給實例添加屬性和方法並使用__slots__

# 創建一個空類
class Person(object):
    pass


a = Person()
# 動態添加屬性,這體現了動態語言的特點(靈活)
a.name = 'jack'
print(a.name)
# 動態添加方法
def say(self):
    print('my name is ' + self.name)
a.speak = say
a.speak(a)
# 這樣添加不太好,因爲哪有自己傳自己的

運行結果:

jack
my name is jack

通過調用其他的一些方法

from types import MethodType
# 動態添加方法

def say(self):
    print('my name is ' + self.name)


a.speak = MethodType(say, a)
a.speak()
# 這樣就不需要給自己傳參了

運行結果:

my name is jack
__ slots __

用於限制實例的屬性的添加
打個比方,只允許給對象添加name, height, weight屬性
在我們定義類的時候,定義一個特殊的屬性 __slots__,可以限制動態的添加屬性。

class Person(object):
    __slots__ = ("name", "age")


a = Person()
# 動態添加屬性,這體現了動態語言的特點(靈活)
a.name = 'jack'
print(a.name)
a.height = 18
print(a.height)

運行結果:

jack
AttributeError: 'Person' object has no attribute 'height'

顯而易見,除了我們指定的一些屬性名之外,其他的屬性都添加不進來

@property

怎麼說呢?私有屬性,我們用方法去訪問很麻煩。肯定是沒有通過直接用屬性來取值玩的爽,所以就有了這個裝飾器
屬性直接對外暴露,不安全,沒有數據的過濾

class Person(object):
    def __init__(self, age):
        self.__age = age
	# 方法名爲受限制的變量,去掉雙下劃線
    @property
    def age(self):
        return self.__age
	# 去掉下劃線.setter
    @age.setter
    def age(self, age):
        if age < 0:
            age = 0
        self.__age = age
p = Person(18)
p.age = 100   # 相當於調用setAge
print(p.age)  # 相當於調用getAge

簡單來講,這個@property裝飾器,就是把一個方法變爲屬性,我們不再需要通過方法來改變屬性了,我們只需要直接通過屬性就可以修改,可以讓我們對受限制訪問的屬性使用語法。簡單方便

運算符重載

讓自定義的類生成的對象(實例)能夠使用運算符進行操作
先看看簡單的列子吧

class Person(object):
   def __init__(self, age):
       self.age = age
       
   # 返回一個對象的描述信息
   def __str__(self):
       return "age = " + str(self.age)
   # 制定加法的規則
   def __add__(self, other):
       return Person(self.age + other.age)


P1 = Person(18)
P2 = Person(20)
print(P1 + P2)
print(P1.__add__(P2))

運行結果:

age = 38
age = 38

是不是很神奇
算數運算符:

方法名 運算符和表達式 說明
__ add __(self,other) self + other 加法
__ sub__(self,other) self - other 減法
__ mul__(self,other) self * other 乘法
__ truediv__(self,other) self / other 除法
__ mod__(self,other) self % other 取餘
__ floordiv__(self,other) self // other 地板除
__ pow__(self,other) self ** other 求冪
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章