1. 程式人生 > >Python——創建類和對象

Python——創建類和對象

刪除 elf ron 知識 減肥 project 順序 引用 示例

####創建類和對象###

1.類的相關知識

類有兩種作用:屬性應用和示例化

1)屬性的引用(類名.屬性)

定義一個類 --> 裏面定義一個屬性(但是這個屬性是寫死在程序裏的) --> 每一個引用這個屬性的都是一樣的內容

2)實例化:類名加括號就是實例化,會自動觸發__init__函數的運行,可以用它來為每個實例定制自己的特有的屬性

關於類裏的方法括號中的self:

self 在實例化時自動將對象/實例本身傳給__init__的第一個參數

self 也可以說是:哪一個對象調用這個方法,self就是哪一個對象的引用

在類封裝的方法內部,self就表示當前調用方法的對象自己

--調用方法時,程序員不需要傳遞self參數(但是定義的時候,第一個參數必須是self)

--在方法內部:可以通過self.訪問對象的屬性

--在方法內部:可以通過self.調用其他的對象方法

示例:

class Cat:

"""這是class Cat的信息"""

def eat(self):

print ‘%s愛吃魚‘ %self.name

def drink(self):

print ‘%s要喝水‘%self.name

# 創建貓對象

tom = Cat()

# 可以使用 .屬性名 利用賦值語句就可以了

#tom.name = ‘Tom‘

tom.eat()

tom.name = ‘Tom‘

tom.drink()

print tom

# lazy_cat = Cat()

# lazy_cat.name = ‘miaomiao‘

# lazy_cat.eat()

# lazy_cat.drink()

2.內置方法

初始化方法:__init__是python對象的內置方法,在使用類名創建對象的時候自動被調用

__init__方法是專門用來定義一個類具有那些屬性和方法的

##如果不用初始化方法,像一些基本屬性可能在創建對象以後,還需要對象.屬性,這樣填寫屬性,還需要print手動去輸出它,添加這個初始化方法,在創建方法之後會主動調用這個方法,將填寫的信息添加並且輸出

##當初始化方法沒有形參變量的時候,方法內部所定義的屬性,在利用該類創建對象的時候,創建的所有對象都會擁有該屬性

##當初始化方法含有形參變量的時候,在利用該類創建對象的時候,創建的所有對象都會自動調用初始化方法,並且會要求添加相應的對象的屬性,如果不添加就執行的話,編譯器會報錯

__del__方法:對象被從內存中銷毀前,會自動調用

__str__方法:返回對象的描述信息 print 對象

__del__方法:在python中,當一個對象被從內存中銷毀前(把這個對象從內存中刪除掉),會自動調用__del__方法

應用場景:

__del__如果希望在對象被銷毀前,再做一些事情,可以考慮一下__del__方法

__str__方法:在python中,使用python輸出對象變量,默認情況下,會輸出這個變量引用的對象是由哪>一個類創建的對象,以及在內存中的地址(十六進制表示).如果在開發中,希望使用print輸出對象變量時,能夠打印自定義的內容,就可以利用__str__這個內置方法了

示例:

1)

class Dog:

def __init__(self,name,weight):

self.name = ‘rourou‘

self.weight = weight

print ‘%s是一個%d斤的狗狗!‘%(self.name,self.weight)

def eat(self):

print ‘%s愛吃肉‘%self.name

def drink(self):

print ‘%s愛喝牛奶‘%self.name

rourou = Dog(‘rourou‘,10)

rourou.eat()

rourou.drink()

print rourou

2)

class Dog:

def __init__(self,name,weight):

self.name = name

self.weight = weight

print ‘%s是一個%d斤重的狗狗!‘%(self.name,self.weight)

def __del__(self):

print ‘內存信息被刪除之前的調用!‘

def __str__(self):

return ‘我是肉肉!‘

dog = Dog(‘rourou‘,10)

print ‘=========‘

print dog

# tom是一個全局變量

# 所以當我們的代碼全部執行完之後,系統才會把tom這個對象進行回收

tom = Cat(‘Tom‘)

print tom

# print tom.name

# # del關鍵字,可以從內存中刪除一個對象,del關鍵字自己調用了__del__方法

# del tom

# print ‘*‘ * 50

生命周期

一個對象從調用類名()創建,聲明周期開始

一個對象的__del__方法一旦被調用,生命周期就結束

在對象的生命周期內,可以訪問對象的屬性,調用對象的方法

3.私有屬性和私有方法

1)私有屬性和私有方法:在屬性或方法前加兩個下劃線 ‘__‘,聲明該方法是私有方法或者屬性,不能在類的外部調用。在類的內部可以調用

私有屬性 就是 對象 不希望公開的 屬性

私有方法 就是 方法 不希望公開的 方法

2)應用場景及定義方式:

應用場景:

在實際開發中,對象的某些屬性或方法可能只希望在對象的內部使用,而不希望在外部被訪問到

定義方法:

在定義屬性或方法時,在屬性名或者方法名前增加兩個下劃線,定義的就是私有屬性或方法

示例:

class Women:

def __init__(self,name):

self.name = name ##這是一個公有屬性

self.__age = 18 ##這是一個私有屬性

def __secret(self): ##這是一個私有方法

print ‘%s 的年齡是 %d‘ %(self.name,self.__age)

lily = Women(‘lily‘)

print lily.name

# 私有屬性,外界不能直接訪問

print lily.age

# 私有方法,外界不能直接調用

lily.__secret()

結果:

會出現報錯,顯示沒有這個屬性,所以說,私有屬性和方法,在類的外部不能被調用

lily

Traceback (most recent call last):

File "/home/kiosk/PycharmProjects/王芳/day06/私有屬性和私有方法.py", line 27, in <module>

print lily.age

AttributeError: Women instance has no attribute ‘age‘

3)類的私有屬性和私有方法

--子類對象不能在自己的方法內部,直接訪問父類的私有屬性和私有方法

--子類對象可以通過父類的公有方法間接訪問到私有屬性或私有方法

私有屬性,私有方法是對象的隱私,不對外公開,外界以及子類都不能直接訪問

私有屬性,私有方法常用做一些內部的事情

示例:

class A:

def __init__(self):

# 在初始化方法中定義兩個屬性,一個公有屬性一個私有屬性

self.num1 = 100 #公有屬性

self.__num2 = 200 #私有屬性

def __test(self):

print ‘私有方法 %d %d‘ % (self.num1, self.__num2)

##如果要查看私有的屬性和方法,可以在類A中定義一個公有方法,然後在公有方法中調用私有的方法和屬性,再print就可以輸出私有的屬性和方法。再在子類直接調用這個公有方法就可以了

def test(self):

print ‘父類的共有方法 %d‘ % self.__num2

self.__test()

class B(A):

def demo(self):

# # 在子類的對象方法中,不能訪問父類的私有屬性

# print ‘訪問父親的私有屬性 %d‘ % self.__num2

# # 在子類對象的方法中,不能調用父類的私有方法

# self.__test()

#調用父類的共有方法

self.test()

# 創建一個子類對象

b = B()

b.demo()

# b.test()

# 在外界不能直接訪問對象有屬性/調用私有方法

# print b.__num2的私

# b.__test()

4.面向對象的三大特征

(1)封裝:根據職責將屬性和方法封裝到一個抽象的類中

(2)繼承:實現代碼的重用,相同的代碼不需要重復的寫

(3)多態

5.單繼承

繼承的概念:子類擁有父類的所有屬性和方法

繼承的語法

class 類名(父類):

def 子類特有的方法

"""

Cat類是Animal類的子類,Animal類是Cat類的父類,Cat從Animal類繼承

Cat類是Animal類的派生類,Animal類是Cat類的基類,Cat類從Animal類派生

"""

class Animal(object):

def eat(self):

print ‘吃‘

def drink(self):

print ‘喝‘

def run(self):

print ‘跑‘

def sleep(self):

print ‘睡‘

class Cat(Animal):

# 子類擁有父類的所有屬性和方法

def call(self):

print ‘喵喵‘

class Dog(Animal):

def bark(self):

print ‘旺旺‘

class Hellokitty(Cat):

def speak(self):

print ‘我可以說日語‘

# 創建一個貓對象

fentiao = Cat()

fentiao.eat()

fentiao.drink()

fentiao.run()

fentiao.sleep()

fentiao.call()

# 創建一個hellokitty對象

# kt = Hellokitty()

# kt.speak()

# kt.call()

# 繼承的傳遞性,子類擁有父類的父類的屬性和方法

"""

繼承的傳遞性:(爺爺 父親 兒子)

1.C類從B類繼承,B類又從A類繼承

2.那麽C類就具有B類和A類的所有屬性和方法

子類擁有父類以及父類的父類中封裝的所有屬性和方法

"""

kt.eat()

kt.drink()

kt.run()

kt.sleep()

# 子類繼承自父類,可以直接享受父類中已經封裝好的方法

# 子類中應該根據自己的職責,封裝子類特有的屬性和方法

6.多繼承

class A:

def test(self):

print ‘A-----test 方法‘

def demo(self):

print ‘A-----demo 方法‘

class B:

def test(self):

print ‘B------test 方法‘

def demo(self):

print ‘B-------demo方法‘

class C(B,A):

"""多繼承可以讓子類對象,同時具有多個父類的屬性和方法"""

"""多繼承(A,B)這個,如果兩個父類的方法重名的話,哪個放在前面就繼承哪個"""

pass

# 創建子類對象

c = C()

c.test()

c.demo()

7.封裝

(1)封裝是面向對象編程的一大特點

(2)面向對象編程的第一步 將屬性和方法封裝到一個抽象的類中(為什麽說是抽象的,因為類不能直接使用)

(3)外界使用類創建對象,然後讓對象調用方法

(4)對象方法的細節都被封裝在類的內部

示例:

小明愛跑步

1.小明體重75.0公斤

2.每次跑步會減肥0.5公斤

3每次吃東西體重會增加1公斤

4.小美的體重是45.0公斤

class Person:

def __init__(self,name,weight):

self.name = name

self.weight = weight

def __str__(self):

return ‘我的名字叫 %s 體重是 %.2f‘ %(self.name,self.weight)

def run(self):

print ‘%s 愛跑步‘ %self.name

# 在對象方法的內部,是可以直接訪問對象的屬性

self.weight -= 0.5

def eat(self):

print ‘%s 吃東西‘ %self.name

self.weight += 1

xx = Person(‘小明‘,75.0)

xx.run()

xx.eat()

print xx

# 同一個類創建出來的多個對象之間,屬性互不幹擾

xm = Person(‘小美‘,45.0)

xm.run()

xm.eat()

print xm

封裝練習:

(1)需求

--房子有戶型,總面積和家具名稱列表

新房子沒有任何家具

--家具有名字和占地面積,其中

床:占4平米

衣櫃:占2平米

餐桌:占1.5平米

--將以上三件家具添加到房子中

--打印房子時,要求輸出:戶型,總面積,剩余面積,家具名稱列表

被使用的類應該先開發

就比如:先要將家具定義出來,然後才能往房子裏面加

# 創建家具類

class HouseItem:

def __init__(self, name, area):

self.name = name

self.area = area

def __str__(self):

return ‘[%s]占地為 %.2f‘ % (self.name, self.area)

# 創建家具

bed = HouseItem(‘bed‘, 4)

print bed

chest = HouseItem(‘chest‘, 2)

print chest

table = HouseItem(‘table‘, 1.5)

print table

# 創建房子類

class House:

def __init__(self, house_type, area):

# 下面為從外界傳遞進來的參數

self.house_type = house_type

self.area = area

# 剩余面積不需要從外面傳遞,內部計算

# 剩余面積 = 總面積 - 家具面積

# 新房子內沒有任何家具,剩余面積=總面積

self.free = area

self.item_list = []

def __str__(self):

return ‘戶型:%s\n總面積:%.2f[剩余面積:%.2f]\n家具:%s‘ \

% (self.house_type, self.area, self.free, self.item_list)

def add_item(self, item):

if item.area >= self.area:

print ‘請重新訂購家具‘

else:

print ‘添加成功‘

self.item_list.append(item.name)

self.free -= item.area

# 創建房子

house = House(‘兩室一廳‘, 100)

house.add_item(bed)

house.add_item(chest)

house.add_item(table)

print house

(2)需求:

--士兵瑞恩有一把AK47

--士兵可以開火(士兵開火扣動的是扳機)

--槍 能夠 發射子彈(把子彈發射出去)

--槍 能夠 裝填子彈 --增加子彈數量

class Gun:

def __init__(self, name):

# 自己輸入槍的型號

self.name = name

# 假設默認的子彈數是10個

self.count = 10

self.free = self.count

def add_zidan(self, num):

if num + self.free > 10:

print ‘子彈數超過10顆!裝子彈失敗‘

else:

self.free += num

print ‘子彈添加成功!‘

def shoot(self):

if self.free <= 0:

print ‘沒有子彈了!‘

else:

self.free -= 1

print ‘開火ing...‘

class Person:

def __init__(self,name):

self.name = name

self.gun = None

def fire(self):

if self.gun == None:

print ‘還沒有槍‘

return

print ‘go!‘

self.gun.shoot()

self.gun.add_zidan(1)

ak47 = Gun(‘AK47‘)

ren = Person(‘ryan‘)

#人使用槍

ren.gun = ak47

ren.fire()

print ren

8.重寫父類方法

(1).覆蓋父類的方法

(2).擴展父類的方法

class Animal:

def eat(self):

print ‘吃‘

def drink(self):

print ‘喝‘

def run(self):

print ‘跑‘

def sleep(self):

print ‘睡‘

class Cat(Animal):

# 子類擁有父類的所有屬性和方法

def call(self):

print ‘喵喵‘

class Hellokitty(Cat):

def speak(self):

print ‘我可以說話‘

def call(self):

# 重寫父類的方法

print ‘話~~‘

# 調用原本在父類中封裝的代碼

Cat.call(self)

# 增加其他的子類代碼

print ‘#!@$@!#!#‘

kt = Hellokitty()

# 如果子類中,重寫了父類的方法

# 在運行中,只會調用在子類中重寫的父類的方法而不會調用父類的方法

kt.call()

重寫的練習:

--在寫好的代碼Bird類的上面,加入一個唱歌的屬性(要增加到默認屬性當中)

class Bird:

def __init__(self):

self.hungry = True

def eat(self):

# 如果吃過了就不餓了

if self.hungry:

print ‘吃東西ing。。。‘

self.hungry = False

else:

print ‘No,thanks!‘

錯誤代碼:

class songBird(Bird):

def __init__(self):

self.sound = ‘squawk!‘

def sing(self):

print self.sound

lb = songBird()

lb.eat()

lb.sing()

print lb

##這就相當於是songBird的初始化方法將原本的代碼的初始化方法覆蓋了,因此就沒有了 self.hungry = True 這行代碼,因此下面的判斷就不能夠執行下去

##正確的代碼應該是,繼承了父類,重寫並且調用父類的被重寫的方法,這樣就相當於是在不更改源代碼的同時,增加了默認的屬性

正確代碼:

class songBird(Bird):

def __init__(self):

self.sound = ‘squawk!‘

Bird.__init__(self) ##這條語句就是調用父類的方法

def sing(self):

print self.sound

lb = songBird()

lb.eat()

lb.sing()

print lb

9.新式類和舊式(經典)類

object是Python為所有對象提供的基類,提供有一些內置的屬性和方法,可以使用dir函數查看

新式類:以object為基類的類,推薦使用

經典類:不以object為基類的類,不推薦使用

python3.X中定義的類時,如果沒有指定父類,會默認使用object作為基類--python3.x中定義的類都是新式類

python2.x中定義類時,如果沒有指定父類,則不會以object作為基類

####推薦使用新式類#############

新式類和舊式類在多繼承時---會影響到方法的搜索順序

為保證編寫的代碼能夠同時在python2.x和python3.x運行

今後在定義類時,如果沒有父類,建議統一繼承自object

10.綜合練習

圖書管理系統

圖書管理系統

1.查詢

2.增加

3.借閱

4.歸還

5.退出

Python——創建類和對象