python模塊和類的通用轉換規則(2),三步轉oo

介紹模塊和類怎麼互相轉換,不談面向對象的繼承 封裝 多態等特色。php

一個person_module模塊,有人的基本屬性和功能。html

person_module.py以下java

# coding=utf8
name = '小明'
eye_color = 'blue'
age = 10

def get_eye_color():
    return name + '的眼睛顏色是: ' + eye_color


def show_age():
    print   name + '的年齡是: ' + str(age)


def grow():
    print name + ' 增加一歲了'
    globals()['age'] += 1   ##這裏要注意必定要這樣寫活着聲明age是全局的,不然會出錯
    print globals()['age']
    show_age()


if __name__ == "__main__":
    print get_eye_color()
    show_age()
    grow()

 

如今假如這個模塊是別人寫的,咱們拿來用,如今咱們要把名字換成小紅,眼睛顏色換成黑色,年齡換成15歲,成長函數,一次增長兩歲python

那咱們就須要修改別人的源碼文件了,可能改着改着改錯了,不知道怎麼復原了。es6

 

那就import這個模塊吧。web

xiaohong.py編程

# coding=utf8
import person_module as p
from person_module import *

p.name = '小紅'
p.age = 14
p.eye_color = 'black'


def grow():
    print p.name + ' 增加一歲了'
    p.age += 2
    print p.age
    show_age()
p.grow = grow


print p.get_eye_color()
show_age()
p.grow()   # 直接grow()也能夠

 

 

 能夠看到屬性被替換了,連增加函數也被替換了,一次增加兩歲。設計模式

這就是給模塊打猴子補丁了,這樣寫很彆扭的實現了模塊繼承,相似於類繼承。函數

 

 

但願把這個模塊轉換成類,oop編程。工具

模塊和類的轉換規則是:

一、模塊級降爲類

二、全局變量改爲實例屬性,全局的不會被改變的變量相似於那種const的,能夠寫成類屬性(減小點內存存儲能夠)。

三、而後把函數改爲方法。方法是類裏面的,函數是模塊裏面的。

 

看person.py

# coding=utf8
class Person(object):
    def __init__(self, name, age,eye_color):
        self.name = name
        self.eye_color = eye_color
        self.age = age

    def get_eye_color(self):
        return self.name + '的眼睛顏色是: ' + self.eye_color

    def show_age(self):
        print self.name + '的年齡是: ' + str(self.age)

    def grow(self):
        print self.name + ' 增加一歲了'
        self.age += 1
        self.show_age()


if __name__ == "__main__":
    xiaohong = Person('小紅', 14, 'black')
    print xiaohong.get_eye_color()
    xiaohong.show_age()
    xiaohong.grow()

 

這樣作了以後,統一經過self就能訪問age name了,改變age也不須要蛋疼的聲明一下age是全局的那個了。
就這樣三個步驟,就能把面向過程的模塊改爲面向對象了。

最主要是前面那種導入模塊的方法,打補丁很麻煩,那例子還只是實現小紅,若是要實現小黃、小花,那就複雜了。若是使用oop,類的多個實例就天然多了,也簡單直觀。

 

 

若是要改變grow方法,繼承一下就好了,改爲這樣

 

大部分入門都是第一種寫法,畢竟py編程太自由了,能夠一條條從上往下指令平鋪,也能夠抽成函數,也能夠oop。用py會長期造成了懶惰的寫法用前面第一種,但複用性真的比oop差不少,整體看起來也low一些。好比多個過程須要共享中間狀態時,單純的使用函數會寫得很糟糕,這時候就應當使用類,不然要麼搞全局變量要麼頻繁的return頻繁的傳參,爲何反對模塊編程,就是由於模塊難以初始化賦值,模塊的多實例難以搞,類能很好解決。非oop一些設計模式很難用上。也有人堅定說他不須要oop,說不須要那是沒認真對比過,或者壓根不瞭解,只是死記硬背類的 繼承 封裝多態這幾個詞語,並無實踐對比過。還有的說python裏面一切皆是對象,因此他寫的就是oop,沒錯,那樣僅限於有int 類 str類 字典類 或者導入了三方庫後有了Request類 Response類,selenim的webdriver的Chrome類 Firefox類,僅限於此啊,沒有本身的類,python一切皆對象(在py裏面隨便寫個 a = 5,a就能夠說是int類的一個實例了,py是面向對象的極致,甚至比java還極致,java裏面的int a = 5,a是基本數據類型,要用到一些必要的方法支持還的把a轉成Interger類的對象,php裏面的字符串操做是由函數完成的,php的小寫字符串轉大寫是 strtoupper("Hello WORLD!"),py的小寫轉大寫是「Hello WORLD!」.uper(),object.func()和func(object)就是op和oo的區別。除了py裏面的例如__len__用,len(str1)來獲取長度,但這種是經過反射完成,也能夠用str.__len__(),len(str)形式上看起來不那麼oo。)雖然py一切皆對象,py是最極致的面向對象,但這不表明隨便寫就是oop編程了。三方庫爲何調用的那麼爽,那是人家oop了,人家三方庫全寫函數,調用起來就知道什麼叫痛苦了,都不知道應該調用哪些函數來處理那個對象了。這都什麼年代了,還對oop持懷疑和反對態度。php py js es6都是在慢慢的後來加入類的概念,難道發明語言的人會比咱們差嗎。

 

必須對py的oop很是熟悉,才能開始學習java。否則的是確定看不懂java。

 

 一個模塊內能夠多個類,類能夠把模塊分割裂更小的模塊組織單元。oo大量實例化時候須要佔用更多的內存,性能是比op差。若是擔憂oo性能比op差,那同樣能夠適當地寫類裏面的靜態方法或者類方法,無需實例化,經常使用的工具方法不要全寫成實例方法,幹個啥都要實例化,該用靜態就要用靜態。

 

這是一些體會,po和oo每次寫時候順便腦補一下,另外一種大概是怎麼樣的。全局變量太多,多個函數操做一個東西,就能夠想下oop,oo能消滅全局,平鋪式的代碼適合簡單腳本,或者快速驗證和測試或者頂層腳本,但若是是做爲被導入模塊,再用這種寫法,模塊裏面大量寫非final類型的全局變量是很腦殘的低級入門寫法。模塊級的po是拿個源碼腳本,處處去修改一些變量的值,例如age name什麼的。oo是對數據和方法的封裝,op是函數和傳參分離在兩個地方。

 

以上爲簡單例子,oop的進階是設計模式。

 

若是不是按照這種寫人的方式,全局變量加函數的面向過程寫法,而是徹底的沒有全局變量一步步return和傳參的,執行三步走那就是隻有class外殼的類,仍然是一個面向過程的類,須要再加一步。

關於pythoh面向過程開發人員三步轉面向對象的補充,再加一步,四步走戰略。轉面向對象也能夠有固定公式。

相關文章
相關標籤/搜索