Python的OOP面向?qū)ο?

# OOP 實(shí)戰(zhàn)通過(guò)簡(jiǎn)單的case 更好的理解OOP思想, 如果使用代碼,可以下載附件修改為.py即可

#!/usr/bin/env python
# -*- coding: utf-8 -*-
'''
Created on 2017年3月24日

@author: fWX457893
'''
# 類的封裝  
class Student(object):
    # __ 雙下劃線可使變量私有變成private,只有在函數(shù)每部可以訪問(wèn),外部不能訪問(wèn),    
    def __init__(self, name, score, **kw):
        self.__name = name
        self.__score = score
        self.kw = kw
    
    # 如果還想要讓外部訪問(wèn),可是添加方法  get_name, get_score, get_kw
    def get_name(self):
        return self.__name
    def get_score(self):
        return self.__score
    # 又要允許外部代碼修改score怎么辦?可以再給Student類增加set_score方法:
    def set_name(self, name):
        self.__name = name
    def set_score(self, score):
        if 0 <= score <= 100:
            self.__score = score
        else :
            raise ValueError('bad score')
    
    def print_score(self):
        print('%s: %s \t %s' % (self.__name, self.__score, self.kw))
        
    def get_grade(self):
        if self.__score >= 90:
            return 'A'
        elif self.__score >= 60:
            return 'B'
        else :
            return"C"

bart = Student('fyh', 100, address='bj')

bart.print_score()

bart.set_score(10)
bart.print_score()

grade = bart.get_grade()
print grade
# 表面上看,外部代碼“成功”地設(shè)置了__name變量,但實(shí)際上這個(gè)__name變量和class內(nèi)部的__name變量不是一個(gè)變量!
# 內(nèi)部的__name變量已經(jīng)被Python解釋器自動(dòng)改成了_Student__name,而外部代碼給bart新增了一個(gè)__name變量。不信試試:
bart.__name = 'new name'
print bart.__name
bart.print_score()

# -------------------------------------------------------------------------------
# OOP 的 繼承和多態(tài)
class Animal(object):
    def run(self):
        print 'Animal is running...'
    def eat(self):
        print('Eating food...')

class Dog(Animal):
    def run(self):
        print('Dog is running...')

    def eat(self):
        print('Dog eating meat...')


class Cat(Animal):
    def run(self):
        print('Cat is running...')

    def eat(self):
        print('Cat eating fish...')


ani = Animal()
ani.run()

cat = Cat()
cat.run()

def run_eat(animal):
    animal.run()
    animal.eat()

run_eat(Animal())
run_eat(Dog())
run_eat(Cat())

'''
對(duì)于一個(gè)變量,我們只需要知道它是Animal類型,無(wú)需確切地知道它的子類型,就可以放心地調(diào)用run()方法,
而具體調(diào)用的run()方法是作用在Animal、Dog、Cat還是Tortoise對(duì)象上,由運(yùn)行時(shí)該對(duì)象的確切類型決定,
這就是多態(tài)真正的威力:調(diào)用方只管調(diào)用,不管細(xì)節(jié),而當(dāng)我們新增一種Animal的子類時(shí),
只要確保run()方法編寫正確,不用管原來(lái)的代碼是如何調(diào)用的。這就是著名的“開(kāi)閉”原則:

對(duì)擴(kuò)展開(kāi)放:允許新增Animal子類;
對(duì)修改封閉:不需要修改依賴Animal類型的run_twice()等函數(shù)。

繼承還可以一級(jí)一級(jí)地繼承下來(lái),就好比從爺爺?shù)桨职?、再到兒子這樣的關(guān)系。而任何類,最終都可以追溯到根類object,這些繼承關(guān)系看上去就像一顆倒著的樹(shù)。

'''

# 
'''
靜態(tài)語(yǔ)言 vs 動(dòng)態(tài)語(yǔ)言

對(duì)于靜態(tài)語(yǔ)言(例如Java)來(lái)說(shuō),如果需要傳入Animal類型,則傳入的對(duì)象必須是Animal類型或者它的子類,否則,將無(wú)法調(diào)用run()方法。
對(duì)于Python這樣的動(dòng)態(tài)語(yǔ)言來(lái)說(shuō),則不一定需要傳入Animal類型。我們只需要保證傳入的對(duì)象有一個(gè)run()方法就可以了:

class Timer(object):
    def run(self):
        print('Start...')
這就是動(dòng)態(tài)語(yǔ)言的“鴨子類型”,它并不要求嚴(yán)格的繼承體系,一個(gè)對(duì)象只要“看起來(lái)像鴨子,走起路來(lái)像鴨子”,那它就可以被看做是鴨子。

Python的“file-like object“就是一種鴨子類型。對(duì)真正的文件對(duì)象,它有一個(gè)read()方法,返回其內(nèi)容。但是,許多對(duì)象,只要有read()方法,都被視為“file-like object“。
許多函數(shù)接收的參數(shù)就是“file-like object“,你不一定要傳入真正的文件對(duì)象,完全可以傳入任何實(shí)現(xiàn)了read()方法的對(duì)象。
'''

class Husky(Dog):
    def run(self):
        print('Husky is running...')

    def eat(self):
        print('Husky eating meat...')
        
# 使用isinstance()
# 對(duì)于class的繼承關(guān)系來(lái)說(shuō),使用type()就很不方便。我們要判斷class的類型,可以使用isinstance()函數(shù)。
# object -> Animal -> Dog -> Husky
animal = Animal()
dog = Dog()
husky = Husky()

print isinstance(husky, Husky), isinstance(husky, Dog), isinstance(husky, Animal)
# True True True  husky 是husky dog object 但是 dog 不是husky 是dog object


#定義一個(gè)父類一個(gè)子類
class Province(object):
    def __init__(self,proname):
        self.proname=proname
    def ps(self):
        print('I am in %s'%self.proname)

class City(Province):
    def __init__(self,proname,cityname):
        self.cityname=cityname
        Province.__init__(self,proname)
    def ps1(self):
        print('I\'m in %s-%s' %(self.proname,self.cityname))

#定義一個(gè)獨(dú)立的類
class Timer(object):
    def ps(self):
        print('我不屬于Province類或其子類,但我有ps方法我同樣可以被調(diào)用')
    def ps1(self):
        print('我不屬于Province類或其子類,但我有ps1方法我同樣可以被調(diào)用')

#定義一個(gè)函數(shù)
def func(x):
    x.ps()
    x.ps1()

#調(diào)用部分
func(City('北京','海淀'))
func(Timer())

# 部分參考廖神的python教程。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容