久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

深入淺出Python元編程

 heii2 2018-09-22

來(lái)源:  碼農(nóng)翻身   作者:劉欣    


隔壁的Java 世界為了創(chuàng)建一個(gè)對(duì)象搞得雞飛狗跳,這邊的Python解釋器倒是樂(lè)得清閑,。 


我作為他的第n任助手正式上崗,。


“老大,有程序員要?jiǎng)?chuàng)建對(duì)象,,怎么辦,?”我向Python解釋器發(fā)出了預(yù)警,,上崗后頭一次遇到這種情況,,我有點(diǎn)緊張,。


class Person:
    def sayHello(self,name):
        print('hello,'+name)

p = Person()

p.sayHello('andy')


“怕啥,我告訴你怎么做啊,,首先找到Metaclass(元類(lèi)),,用元類(lèi)來(lái)創(chuàng)建Class, 最后用Class對(duì)象來(lái)創(chuàng)建實(shí)例?!?  老大說(shuō)著還給我畫(huà)了個(gè)圖: 



 “不是吧,!剛才還說(shuō)人家Java雞飛狗跳,我看我們這兒也絲毫不差,,一個(gè)Class(如Person)在內(nèi)存中用個(gè)對(duì)象來(lái)表示我理解,,畢竟在我們的世界中,一切都是對(duì)象嘛,, 但是這Metaclass(元類(lèi))是什么鬼,?”  


“是啊,類(lèi)是一個(gè)對(duì)象,調(diào)用這個(gè)類(lèi)對(duì)象的__new__方法就可以創(chuàng)建出這個(gè)類(lèi)的實(shí)例,。那么問(wèn)題來(lái)了,, 類(lèi)對(duì)象是怎么來(lái)的?怎么把這個(gè)類(lèi)對(duì)象給new 出來(lái),?”  老大沒(méi)有回答,,只是反問(wèn)。  


“不是程序員寫(xiě)的嗎,, class Person.....”  我有點(diǎn)底氣不足,。 


“程序員寫(xiě)的只是代碼,都是文本而已,,我們?cè)趫?zhí)行的過(guò)程中需要用Metaclass 把這個(gè)Person類(lèi)對(duì)象給創(chuàng)建起來(lái)的,?!?nbsp;


“可是我也沒(méi)有看到Person類(lèi)的Metaclass?。?! 他到底在哪兒,?”  


“那是你沒(méi)有找到, Person類(lèi)中沒(méi)有,,就去它的父類(lèi)中去找,,如果也沒(méi)有,就繼續(xù)向父類(lèi)的父類(lèi)去找,,如果在任何父類(lèi)中都找不到Metaclass,,就去模塊中去找,如果還是找不到,,就用缺省的Metaclass,,即type?!?nbsp;


我按照老大的要求,,去找這個(gè)Metaclass,沒(méi)有找到,,只好用缺省的type了,。


可是我記得這個(gè)type不是個(gè)類(lèi),是個(gè)函數(shù)啊,,可以用來(lái)查看一個(gè)變量的類(lèi)型:


>>> type(1)
class 'int'>
>>> type('aaa')
class 'str'>
>>>


老大說(shuō):“這個(gè)type啊,,還有另外一個(gè)用法,可以創(chuàng)建其他類(lèi)對(duì)象,,在創(chuàng)建的時(shí)候,,需要三個(gè)參數(shù):”


1. 要?jiǎng)?chuàng)建的類(lèi)對(duì)象的名稱(chēng),例如'Person' 

2. 要?jiǎng)?chuàng)建的類(lèi)對(duì)象的父類(lèi),例如(object,) 

3. 包含屬性的字典,,即類(lèi)的屬性和方法,。例如{'sayHello': sayHello} 


比如,下面這段代碼也創(chuàng)建了一個(gè)類(lèi)對(duì)象Person,,和程序員寫(xiě)的class Person...  效果是一樣的,。


def sayHello(self,name):
    print('hello,'+name)

#通過(guò)type來(lái)創(chuàng)建一個(gè)類(lèi)對(duì)象,名稱(chēng)為Person,,這個(gè)類(lèi)對(duì)象有一個(gè)方法sayHello
Person = type('Person',(),{'sayHello':sayHello})

#通過(guò)類(lèi)對(duì)象來(lái)創(chuàng)建實(shí)例
p = Person()

p.sayHello('andy')  # hello andy 

(友情提示:可左右滑動(dòng))


嘿,,這個(gè)辦法不錯(cuò)啊,可以在運(yùn)行時(shí),、動(dòng)態(tài)地創(chuàng)建一個(gè)全新的類(lèi)出來(lái),!隔壁的Java雖然也能做到,但是得利用ASM之類(lèi)工具去直接操作字節(jié)碼,,太麻煩了,,我大Python直接通過(guò)普普通通、簡(jiǎn)簡(jiǎn)單單的Python代碼就搞定了,!


這就是動(dòng)態(tài)腳本語(yǔ)言的一個(gè)優(yōu)勢(shì)吧,! 


之前聽(tīng)說(shuō)過(guò)元編程,現(xiàn)在應(yīng)該就是元編程了吧,?但是這個(gè)Metaclass到底有什么用處呢,? 程序員為什么不直接在代碼中寫(xiě)class Person..... 這樣的代碼? 這樣多直觀啊,。


老大說(shuō):“有些程序員會(huì)自定義Metaclass,,這些自定義的Metaclass 主要做這些事情:” 


1. 攔截類(lèi)的創(chuàng)建 

2. 讀取類(lèi)的信息,可能做修改 

3. 返回新的類(lèi),。 


攔截類(lèi)的創(chuàng)建,? 為什么有這樣“變態(tài)”的需求?


我真想看看一個(gè)自定義的Metaclass,,看看它到底是怎么“變態(tài)”的,。 


沒(méi)多久,機(jī)會(huì)來(lái)了,,又要?jiǎng)?chuàng)建對(duì)象了,。 


from django.db import models

class Employee(models.Model):
    name = models.CharField(maxlength = 50)    
    age  = models.IntegerField()
    #其他代碼略#


在Employee中沒(méi)有看到Metaclass, 我就去父類(lèi)Model中去尋找,運(yùn)氣不錯(cuò),,一下子就找到了metaclass ,,叫做ModelBase:


class Model(metaclass=ModelBase):
    #其他代碼略


趕緊去看ModelBase的代碼,唉,,實(shí)在是有點(diǎn)復(fù)雜了,,讓我看得頭暈。 


老大說(shuō):“你不用花費(fèi)時(shí)間了,你的前任的前任曾經(jīng)研究過(guò)它,,是為了實(shí)現(xiàn)ORM ,!” 


“ORM?” 


“就是對(duì)象和關(guān)系數(shù)據(jù)庫(kù)的映射,。你想想,,程序員創(chuàng)建的Python對(duì)象想要保存到數(shù)據(jù)庫(kù)中,該怎么辦,?“ 老大問(wèn)道,。


”那還不簡(jiǎn)單,程序員可以寫(xiě)SQL代碼啊,,insert into employee(name,age) values(?,?),,其中包含那個(gè)Employee對(duì)象的name ,age的值不就行了?“


”那樣就有點(diǎn)笨拙了,,你再想想,,能不能簡(jiǎn)化程序員的工作,別讓他們?nèi)?xiě)這些煩人的,、容易出錯(cuò)的SQL代碼,?能不能讓框架來(lái)做這件事?“ 老大寫(xiě)了兩行代碼。


employee = Employee(name='andy',age=20)  
employee.save()


“看看,,程序員只要把對(duì)象創(chuàng)建出來(lái),調(diào)用下save方法就行了,,SQL語(yǔ)句就會(huì)形成,,保存到數(shù)據(jù)庫(kù)中?!?/span>

(注:這里略過(guò)了數(shù)據(jù)庫(kù)連接的管理)


“難道ModelBase這個(gè)元類(lèi)在后面做‘手腳',?”我似乎有點(diǎn)理解了。


”沒(méi)錯(cuò),,你看到這些Employee類(lèi)的屬性沒(méi)有,? 就是程序員寫(xiě)的那些name, age...... 程序員這么寫(xiě),其實(shí)就是在告訴ModelBase,,尊敬的Metaclass 啊,, 這些都是數(shù)據(jù)庫(kù)的列啊,列名是 name, 類(lèi)型是char(50) ,, 還有個(gè)列名是age,,是個(gè)整數(shù)?!?nbsp;



 “那個(gè)MetaClass ,,對(duì),就是ModelBase會(huì)讀取這些列名、類(lèi)型,,并且記錄下來(lái),。 有了列名的信息,將來(lái)就可以形成insert, update,delete等SQL語(yǔ)句了,。對(duì)不對(duì),?”


原來(lái)如此!看來(lái)ModelBase在創(chuàng)建Employee類(lèi)對(duì)象的時(shí)候,,“偷偷地”讀取了Employee類(lèi)的定義信息,,這樣才能在背后實(shí)現(xiàn)ORM! 



我按照老大的指示,,調(diào)用ModelBase的__new__方法,,創(chuàng)建了Employee類(lèi)對(duì)象。 


接下來(lái)又調(diào)用Employee類(lèi)對(duì)象的__new__方法,,創(chuàng)建了Employee實(shí)例對(duì)象,。  


employee = Employee(name='andy',age=20)  
employee.save()


當(dāng)程序員調(diào)用employee.save()方法的時(shí)候,正如老大所說(shuō),,神奇的魔法發(fā)生了,,一條sql語(yǔ)句形成,并且發(fā)送給了數(shù)據(jù)庫(kù)去執(zhí)行,。


我感慨到:“這Python的元編程還是真是不錯(cuò)啊,,能在運(yùn)行時(shí)動(dòng)態(tài)地修改類(lèi),比隔壁的Java強(qiáng)多了,!”


“Python元編程的技術(shù)不僅僅是Metaclass,,還多著呢,你慢慢學(xué)吧,!”

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,,所有內(nèi)容均由用戶(hù)發(fā)布,不代表本站觀點(diǎn),。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式,、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(jǐn)防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶(hù) 評(píng)論公約

    類(lèi)似文章 更多