類與對象與面向對象編程

類的定義

  • 現實世界中事物的描述、定義
  • 描述對象包含的數據和特徵
  • 注意類與對象的區別

類的創建和使用

創建

  • 類名使用大駝峯命名方式,但是首字母大寫,不適用下劃線_
  • 實例名和模塊名使用小寫字母,並在單詞之間加下劃線_
  • 類與類之間使用2個空行分隔
  • 類的不同方法之間使用1個空行分隔
  • class ClassName():
class Dog(): #類名,大駝峯命名法
    '''
    模擬狗類動物
    '''
    def __init__(self, name, age): #構造函數,類的默認方法,前後2個雙下劃綫與普通方法區分
        '''
        初始化狗的name和age
        :param name:
        :param age:
        '''
        self.name = name
        self.age = age

    def sit(self):
        '''
        蹲下動作
        :return:
        '''
        print('{0} is now sitting.'.format(self.name.title()))

    def roll_over(self):
        '''
        打滾動作
        :return:
        '''
        print('{0} rolled over!'.format(self.name.title()))


__init__()構造函數

  • 創建類的實例時,自動調用
  • 形參self必不可少,且位於其他形參前面
  • 每個與類相關聯的方法調用都自動傳遞self,它是指向實例本身的引用

__del__()析構函數

  • Python中不需要特別使用析構函數

垃圾回收器

  • gc模塊collect()函數

類的方法

  • 必須有self參數
  • 調用類的方法是,可以不傳遞self參數

類的使用(實例化)

  • 創建對象的過程稱之爲類的實例化
  • 直接賦值
my_dog = Dog('willie',6)
print('My dog\'s name is {0},and it\'s {1} years old!'.format(my_dog.name,my_dog.age))
my_dog.sit()
my_dog.roll_over()

your_dog = Dog('lucy',3)
print('Your dog\'s name is {0},and it\'s {1} years old!'.format(your_dog.name,your_dog.age))
your_dog.sit()
your_dog.roll_over()

修改類中屬性值

  • 1.直接修改屬性值
  • 2.通過方法修改屬性值
class Car():
    '''
    模擬汽車
    '''
    def __init__(self, make, model, year):
        self.make = make
        self.model = model
        self.year = year
        self.odometer_reading = 0 #爲屬性指定默認值

    def get_descriptive_name(self):
        '''
        輸出汽車信息
        :return:
        '''
        return '{0} {1} {2}'.format(self.year,self.make,self.model).title()

    def update_odometer(self, mileage):
        '''
        更新里程數
        禁止將里程數回調
        '''
        if mileage > self.odometer_reading:
            self.odometer_reading = mileage
        else:
            print('You can\'t roll back an odometer!')

    def increment_odometer(self, miles):
        '''
        汽車裏程數增加指定的值
        禁止將里程數回調,也即禁止增加負數值
        :param miles:
        :return:
        '''
        if miles > 0:
            self.odometer_reading += miles
        else:
            print('You can\'t roll back an odometer!')

    def read_odometer(self):
        '''
        打印汽車裏程數
        '''
        print('This car has {0} miles on it'.format(self.odometer_reading))


my_new_car = Car('audi', 'a4', 2016)
print(my_new_car.get_descriptive_name())
my_new_car.read_odometer()

my_new_car.odometer_reading = 23 #通過實例,直接修改屬性值
my_new_car.read_odometer()

my_new_car.update_odometer(123) #通過方法1,修改屬性值
my_new_car.read_odometer()

my_new_car.increment_odometer(100) #通過方法2,修改屬性值
my_new_car.read_odometer()

關於類屬性與實例屬性

  • 在不對實例屬性重新賦值的情況下,類屬性與實力屬性指向同一內存地址
  • 使用__class__.var調用類屬性
class A():
    name = 'Leo'
    age = 28

    def say(self):
        self.name = 'bbb'
        self.age = 18
        print('Hi,{0}'.format(__class__.name)) #調用類屬性name

print(A.name)
print(A.age)
print(id(A.name))
print(id(A.age))
a1 = A()
print(a1.name)
print(a1.age)
print(id(a1.name))
print(id(a1.age))
a1.name = 'ccc'
a1.age = 10
print(a1.name)
print(a1.age)
print(id(a1.name))
print(id(a1.age))
a1.say() #

執行結果:

Leo
28
31302744
491811136
Leo
28
31302744
491811136
ccc
10
43679392
491810560
Hi,Leo

類的繼承

  • 子類繼承父類時,會繼承父類的所有屬性和方法
  • 子類也可以定義自己特有的屬性和方法
  • 父類必須包含在子類當前的文件中,且位於子類前面
  • super()特殊函數,也叫超類,代表父類,用於關聯子類與父類
  • 有時需要在子類中對父類方法進行重寫,此時父類中的舊方法會在調用時被忽略
  • 當一個類的屬性和方法過多時,可以將其中一部分屬性與方法分拆出來,定義新的類,然後可以將新類的實例化對象當做屬性來賦值
  • object類是所有類的父類,也稱爲基類
class Car():
    '''
    模擬汽車
    '''
    def __init__(self, make, model, year):
        self.make = make
        self.model = model
        self.year = year
        self.odometer_reading = 0 #爲屬性'汽車裏程數'指定默認值0

    def get_descriptive_name(self):
        '''
        返回汽車信息摘要
        :return:
        '''
        return '{0} {1} {2}'.format(self.year,self.make,self.model).title()

    def update_odometer(self, mileage):
        '''
        更新里程數
        禁止將里程數回調
        '''
        if mileage > self.odometer_reading:
            self.odometer_reading = mileage
        else:
            print('You can\'t roll back an odometer!')

    def increment_odometer(self, miles):
        '''
        汽車裏程數增加指定的值
        禁止將里程數回調,也即禁止增加負數值
        :param miles:
        :return:
        '''
        if miles > 0:
            self.odometer_reading += miles
        else:
            print('You can\'t roll back an odometer!')

    def read_odometer(self):
        '''
        返回汽車裏程數
        '''
        print('This car has {0} miles on it'.format(self.odometer_reading))

    def fill_gas_tank(self):
        '''
        車輛充電/加油信息
        :return:
        '''
        print('Fill gas tank!')

class ElectricCar(Car): #子類ElectricCar繼承父類Car
    '''
    電動汽車
    '''
    def __init__(self, make, model, year):
        '''
        初始化父類屬性
        初始化電動汽車特有屬性
        :param make:
        :param model:
        :param year:
        '''
        super().__init__(make, model, year) #調用父類的方法__init__(),讓ElectricCar實例包含Car類的所有屬性
        self.battery = Battery() #新增屬性,此時會生成新的實例Battery,將新的實例作爲屬性賦值給self.battery,也就是說,每當創建ElectricCar實例,初始化時,會同步創建新的Battery實例


    def fill_gas_tank(self): #重寫父類的方法fill_gas_tank
        '''
        電動汽車沒有郵箱
        :return:
        '''
        print('This car doesn\'t need a gas tank!')

class Battery():
    '''
    模擬電動汽車的電瓶
    '''
    def __init__(self, battery_size = 70):
        self.battery_size = battery_size

    def describe_battery(self):
        print('This car has a {0} -kwh battery.'.format(self.battery_size))

    def get_range(self):
        '''
        返回續航里程
        :return:
        '''
        if self.battery_size == 70:
            range = 240
        elif self.battery_size == 85:
            range = 270
        print('This car go approximately {0} miles on a full charge.'.format(range))

my_tesla = ElectricCar('tesla','model s',2016)
print(my_tesla.get_descriptive_name())

my_tesla.fill_gas_tank()
my_tesla.battery.describe_battery()
my_tesla.battery.get_range()

導入類

  • 將類存儲在模塊中,在主程序中導入所需要的模塊
  • import 導入
  • 高效的編程方式,不同的功能存儲在不同的模塊中
  • 導入模塊時,先導入標準庫,後導入自定義庫,之間用空行分隔
import car 

my_beetle = car.Car('volkswagen','beetle',2016)
print(my_beetle.get_descriptive_name())
my_beetle.odometer_reading = 23
my_beetle.read_odometer()

my_tesla = car.ElectricCar('tesla','roadster',2016)
print(my_tesla.get_descriptive_name())
my_tesla.battery.describe_battery()
my_tesla.battery.get_range()

類的屬性

  • 1.私有屬性
    __雙下劃線前綴,私有屬性
  • 2.公有屬性【靜態屬性|類屬性】
    沒有雙下劃線前綴,共有屬性
  • 3.實例屬性
    有self前綴,實例屬性
  • 4.內置屬性
    __dict__
    __bases__
    __doc__
    __module__
class Fruit():
    price = 0 #類屬性

    def __init__(self):
        self.color = 'red' #實例屬性
        zone = 'China' #局部變量,不能被實例化對象調用
        __number = 100 #私有屬性

class Apple(Fruit):
    pass

if __name__ == '__main__':
    print(Fruit.price) #返回類屬性
    apple = Fruit()
    print(apple.color) #返回實例屬性
    #報錯 print(apple.zone)
    Fruit.price += 10
    print(apple.price)
    banana = Fruit()
    print(banana.price)
    #報錯 print(banana._Fruit__number)
    print(Fruit.__dict__) #Fruit類的內置屬性__dict__
    print(Fruit.__bases__) #Fruit類的內置屬性__bases__
    print(Fruit.__module__) #Fruit類的內置屬性__module__
    print(Fruit.__doc__) #Fruit類的內置屬性__doc__

類的方法

類的內置方法

__init__    #初始化對象
__del__ #釋放對象
__new__ #生成實例
__str__ #使用print時調用
__getitem__ #獲取序列索引key對應的值
__len__ #使用len()時調用
__cmp   #比較兩個對象
__getattr__ #獲取屬性值
__setattr__ #設置屬性值
__delattr__ #刪除屬性
__getattribute__    #獲取屬性值
__gt__  #判斷是否大於
__it__  #判斷是否小於
__ge__  #判斷是否大於等於
__le__  #判斷是否小於等於
__eq__  #判斷是否等於
__call__    #將實例作爲函數調用

類的內置方法實現對象之間的運算

  • 對象之間進行關係運算,也叫運算符的重載
  • 通過類的內置方法實現,例如__gt__

類方法

  • 1.私有方法
    __雙下劃線前綴,私有方法
  • 2.公有方法
    沒有雙下劃線前綴,共有方法
  • 3.靜態方法
    @ staticmethod
  • 4.類方法
    @ classmethod
class Fruit():
    price = 0

    def __init__(self):
        self.__color = 'red'

    def getColor(self):   #公有方法
        print(self.__color)

    @ staticmethod #@ classmethod  靜態方法/類方法
    def getPrice():
        print(Fruit.price)

    def __getPrice():
        Fruit.price += 10
        print(Fruit.price)

    count = staticmethod(__getPrice) #把__getPrice()轉換爲靜態方法,並賦值給count,也即count()爲靜態方法

if __name__ == '__main__':
    apple = Fruit()
    apple.getColor()
    Fruit.count()
    banana = Fruit()
    Fruit.count()
    Fruit.getPrice()

類方法的動態特性

  • 可以將已經定義好的方法,動態添加到類中,稱爲新的方法
class Fruit():
    pass

def add(self):
    print('Grow...')

Fruit.grow = add #將新定義的方法add,直接動態加入到Fruit類中,重命名爲grow
fruit1 = Fruit()
fruit1.grow() #調用新增加的grow方法

類的嵌套

  • Python類中可以再定義類,但是不推薦這麼使用,會導致程序難以理解

抽象類

多態性

多重繼承

  • 導致程序複雜,不易維護

典型案例

class Person():
    def __init__(self):
        pass

    def __setattr__(self, key, value):
        print('設置屬性:{0}'.format(key))
        super().__setattr__(key,value)
        print('{0}:{1}'.format(key,value))

p = Person()
print(p.__dict__)
p.age = 18
class Person:
    # 實例方法
    def eat(self):
        print(self)
        print("Eating.....")

    # 類方法
    # 類方法的第一個參數,一般命名爲cls,區別於self
    @classmethod
    def play(cls):
        print(cls)
        print("Playing.....")

    # 靜態方法
    # 不需要用第一個參數表示自身或者類
    @staticmethod
    def say():
        print("Saying....")


leo = Person()

# 實例方法
leo.eat()
# 類方法
Person.play()
leo.play()
# 靜態方法
Person.say()
leo.say()
class Student():
    def __init__(self, name):
        self._name = name

    def __gt__(self, other):
        print("{0}比{1}大嗎?".format(self._name, other._name))
        return self._name > other._name

stu1 = Student("one")
stu2 = Student("two")
print(stu1 > stu2)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章