類的定義
- 現實世界中事物的描述、定義
- 描述對象包含的數據和特徵
- 注意類與對象的區別
類的創建和使用
創建
- 類名使用大駝峯命名方式,但是首字母大寫,不適用下劃線_
- 實例名和模塊名使用小寫字母,並在單詞之間加下劃線_
- 類與類之間使用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)