Python面向對象-封裝 繼承 多態

1.使用類名創建對象的時候,創建對象,Python解釋器

會自動爲對象在內存中分配空間。調用初始化方法爲對象的屬性設置初始值

這個初始化方法是init方法

使用類名創建對象的時候哦,會自動調用初始化方法

2.繼承的語法
class 類名(父類)
def 子類特意有的方法

重寫父類方法有兩種情況
1.覆蓋父類方法 2.對父類方法進行擴展

1.覆蓋父類的方法
如果在開發中,父類父類方法的實現和子類方法的實現
完全不同,就可以使用覆蓋的方式
在子類中重新編寫父類的方法

具體實現方式,就相當於在子類中定義了
一個和父類同名的方法並實現
重寫之後 在運行時 只會調用子類的重寫方法
而不會再調用父類封裝的方法

對父類的方法進行擴展
如果在開發中,子類的方法實現包含父類的方法實現
(父類原本封裝的方法實現是子類方法的一部分就可以
使用擴展方法)
1.在子類中重寫父類的方法
2.在需要的位置使用 父類名。方法(self)來調用父類方法
的執行(使用父類名稱調用父類方法)
3.代碼其他的位置針對子類的需求,編寫子類特有的代碼實現

“””
繼承的傳遞性:(爺爺 父親 兒子)
1.C類從B類繼承,B類又從A類繼承
2.那末C類就具有B類和A類的所有屬性和方法
子類具有父類及父類的父類中封裝的所有屬性和方法

“””
繼承自己示例

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.eat +=1.0

xiaoming = Person('xiaoming',50.0)
xiaoming.run()
print xiaoming

小狗愛睡覺 小狗愛亂跳示例

class dog():
    def sleep(self):
        print '小狗愛睡覺'
    def jump(self):
        print '小狗愛亂跳'

jia = dog()
jia.sleep()
jia.jump()
print jia
addr = id(jia)
#%x:打印格式爲十六進制
print '%x' % addr
#%d:打印格式爲十進制
print '%d' % addr

#再創建一個狗類對象
lazy_dog = dog()
lazy_dog.sleep()
lazy_dog.jump()
print lazy_dog

fool_dog = lazy_dog
print fool_dog

示例三

class Cat():
    def __init__(self,new_name):
        self.name = new_name
        print '%s 來了' % self.name
    def __del__(self):
        print '%s 走了' % self.name

tom = Cat('tom')
print tom.name

del tom
print '-' * 50

繼承的傳遞性:(爺爺 父親 兒子)
1.C類從B類繼承,B類又從A類繼承
2.那末C類就具有B類和A類的所有屬性和方法
子類具有父類及父類的父類中封裝的所有屬性和方法

"""
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 redcat(Cat):
    def speak(self):
        print 'yiyiyi'


Tom = Animal()
Tom.eat()
Tom.drink()
Tom.run()
Tom.sleep()

單繼承
1.繼承的概念,語法和特點
繼承的概念:子類擁有父類的所有方法和屬性(子類只需要封裝自己特有的)
2.繼承的語法
class 類名(父類)
def 子類特意有的方法

重寫父類方法有兩種情況
1.覆蓋父類方法 2.對父類方法進行擴展

1.覆蓋父類的方法
如果在開發中,父類父類方法的實現和子類方法的實現
完全不同,就可以使用覆蓋的方式
在子類中重新編寫父類的方法

具體實現方式,就相當於在子類中定義了
一個和父類同名的方法並實現
重寫之後 在運行時 只會調用子類的重寫方法
而不會再調用父類封裝的方法

對父類的方法進行擴展
如果在開發中,子類的方法實現包含父類的方法實現
(父類原本封裝的方法實現是子類方法的一部分就可以
使用擴展方法)
1.在子類中重寫父類的方法
2.在需要的位置使用 父類名。方法(self)來調用父類方法
的執行(使用父類名稱調用父類方法)
3.代碼其他的位置針對子類的需求,編寫子類特有的代碼實現

示例一

class Bird():
    def __init__(self):
        self.hungry = True
    def eat(self):
        if self.hungry:
            print 'Aaaaaaa'
            self.hungry =False
        else:
            print 'No Thinks!'

class SingBird(Bird):
    def __init__(self):
        self.sound = 'Squawk'
        Bird.__init__(self)
    def sing(self):
        print self.sound


#bird = Bird
#bird.eat()

littlebird = SingBird()
littlebird.eat()
littlebird.sing()

示例二

"""
class A():
    #def test(self):
        print '----------'
    def demo(self):
        print '+++++++++++'
class B():
    def test(self):
        print '**********'
    #def demo(self):
        print '==========='
class C(B,A):
    pass


c = C()
c.test()
c.demo()

新式類 舊式類(經典類)

In [1]: class A(): #舊式類 繼承的功能少
   ...:     pass
   ...: 

In [2]: a = A()

In [3]: dir(a)
Out[3]: ['__doc__', '__module__']

In [4]: class B(object): #新式類  繼承功能多
   ...:     pass
   ...: 

In [5]: b = B()

In [6]: dir(b)
Out[6]: 
['__class__',
 '__delattr__',
 '__dict__',
 '__doc__',
 '__format__',
 '__getattribute__',
 '__hash__',
 '__init__',
 '__module__',
 '__new__',
 '__reduce__',
 '__reduce_ex__',
 '__repr__',
 '__setattr__',
 '__sizeof__',
 '__str__',
 '__subclasshook__',
 '__weakref__']

封裝房子示例

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' ,5)
print chest
tables = HouseItem('tables' ,1.5)
print tables

class House():
    def __init__(self,house_type,area):
        self.house_type = house_type
        self.area = area
        self.free_area = area
        self.item_list = []
    def __str__(self):
        return '戶型:%s\n總面積:%.2f [剩餘面積:%.2f]\n傢俱列表:%s\n' \
              %(self.house_type,self.area,self.free_area,self.item_list)
    def add_item(self, item):
        print '要添加 %s' % item
        if item.area > self.free_area:
            print '%s 的面積太大,無法添加' % item.name
        self.item_list.append(item.name)
        self.free_area -= item.area


my_house = House('兩室一廳',100)
my_house.add_item(bed)
my_house.add_item(chest)

封裝士兵開槍示例

class Gun():
    def __init__(self,model):
        #槍的型號
        self.model = model
        #子彈數量
        self.bullet_count = 0
    def add_bullet(self,count):
        self.bullet_count += count
    def shoot(self):
        #1.判斷子彈的數量
        if self.bullet_count <= 0:
            print '%s 沒有子彈了' %self.model
            return
        #2.發射子彈
        print '%s 突突突 %d' % (self.model,self.bullet_count)
class Soldier():   #定義!
    def __init__(self,name):
        self.name = name
        self.gun = None
    def fire(self):
        #判斷士兵有沒有槍
        if self.gun == None:
            print '%s 還沒有槍哈哈哈' %self.name
            return
        #高喊口號
        print 'go go go %s' %self.name
        #讓槍裝子彈
        self.gun.add_bullet(50)
        #讓槍發射子彈
        self.gun.shoot()

#1.創建槍對象
ak47 = Gun('AK47')
ak47.add_bullet(50)
ak47.shoot()

#2.創建士兵
ryan = Soldier('Ryan')
ryan.gun = ak47
ryan.fire()
print ryan.gun

多態:不同的子類(繼承知識)對象調用相同的方法,產生不同的結果

class Jia(object):
    def __init__(self,name):
        self.name = name
    def say(self):
        print '%s amazing'% self.name

class Mr(Jia):
    def say(self):
        print '%s happily'% self.name


hh = Jia('hh')

多態

類具有繼承關係,並且子類類型可以向上轉型看做父類類型,如果我們從 Person 派生出 Student和Teacher ,並都寫了一個 whoAmI() 方法:

class Person(object):
    def __init__(self, name, gender):
        self.name = name
        self.gender = gender
    def whoAmI(self):
        return 'I am a Person, my name is %s' % self.name

class Student(Person):
    def __init__(self, name, gender, score):
        super(Student, self).__init__(name, gender)
        self.score = score
    def whoAmI(self):
        return 'I am a Student, my name is %s' % self.name

class Teacher(Person):
    def __init__(self, name, gender, course):
        super(Teacher, self).__init__(name, gender)
        self.course = course
    def whoAmI(self):
        return 'I am a Teacher, my name is %s' % self.name

在一個函數中,如果我們接收一個變量 x,則無論該 x 是 Person、Student還是 Teacher,都可以正確打印出結果:

def who_am_i(x):
    print x.whoAmI()

p = Person('Tim', 'Male')
s = Student('Bob', 'Male', 88)
t = Teacher('Alice', 'Female', 'English')

who_am_i(p)
who_am_i(s)
who_am_i(t)
#運行結果:

#I am a Person, my name is Tim
#I am a Student, my name is Bob
#I am a Teacher, my name is Alice

這種行爲稱爲多態。也就是說,方法調用將作用在 x 的實際類型上。s 是Student類型,它實際上擁有自己的 whoAmI()方法以及從 Person繼承的 whoAmI方法,但調用 s.whoAmI()總是先查找它自身的定義,如果沒有定義,則順着繼承鏈向上查找,直到在某個父類中找到爲止。

由於Python是動態語言,所以,傳遞給函數 who_am_i(x)的參數 x 不一定是 Person 或 Person 的子類型。任何數據類型的實例都可以,只要它有一個whoAmI()的方法即可:

class Book(object):
    def whoAmI(self):
        return 'I am a book'

這是動態語言和靜態語言(例如Java)最大的差別之一。動態語言調用實例方法,不檢查類型,只要方法存在,參數正確,就可以調用。

任務

Python提供了open()函數來打開一個磁盤文件,並返回 File 對象。File對象有一個read()方法可以讀取文件內容:

例如,從文件讀取內容並解析爲JSON結果:

import json
print json.load(f)

由於Python的動態特性,json.load()並不一定要從一個File對象讀取內容。任何對象,只要有read()方法,就稱爲File-like Object,都可以傳給json.load()。

請嘗試編寫一個File-like Object,把一個字符串 r’[“Tim”, “Bob”, “Alice”]’包裝成 File-like Object 並由 json.load() 解析。

?不會了怎麼辦

只要爲Students類加上 read()方法,就變成了一個File-like Object。

參考代碼:

import json

class Students(object):
    def read(self):
        return r'["Tim", "Bob", "Alice"]'

s = Students()

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