你們單位在國外搞了個伺服器,立足於美利堅,受美國法律保護。用來存放你懂的資源,以圖片和電影為主。最近流量非常可觀,為了更好的服務客戶,改善用戶體驗。 你們老闆決定增加一個投票區,用戶可以給自己喜愛的作品投票,每個月評出最喜愛作品,並且從用戶中挑選3名用戶作為獲獎用戶,獎品為蒼老師簽名寫真集。這還不簡 ...
你們單位在國外搞了個伺服器,立足於美利堅,受美國法律保護。用來存放你懂的資源,以圖片和電影為主。最近流量非常可觀,為了更好的服務客戶,改善用戶體驗。
你們老闆決定增加一個投票區,用戶可以給自己喜愛的作品投票,每個月評出最喜愛作品,並且從用戶中挑選3名用戶作為獲獎用戶,獎品為蒼老師簽名寫真集。這還不簡單
不就是一個投票嘛,先寫一個類,咔咔你就寫完了,代碼是這樣的。
class MovieVoted(object): def __init__(self, title, score, actor): self.title = title self.score = score self.actor = actor def voted(self, value): return {'title':self.title,'score':self.score,'actor':self.actor}
很快你把代碼完善以後就上線,對自己的結果很滿意。想必老闆也會給升職加薪,到時候迎娶前臺妹子過上人生巔峰。正當陶醉在美夢的時候,突然聽到老闆在辦公室罵罵咧咧:哪個傻X做的。
這時候你感覺不對,立馬上到你們的網站,看到你們的評選域出現了很多負分,電影評分是負分怎麼行呢。原來是隔壁老李和你們家乾的是一樣的業務,發現你們有這個功能以後就到你們把電
影評分都評為負的,給用戶帶來了不好的體驗。老闆罵了你一頓後,並且告訴你今天不把這個事情解決明天就不用來了。
面對需求毫無頭緒,難道人生就是這麼殘酷麽。你立馬想到去年在東莞時認識的程式員老王,老王畢竟是大廠工程師,見過大世面,想必很多奇淫技巧不在話下。於是你就給老王打電話
老王好像不方便,聽那聲音好像在跑步。5分鐘後老王給你回了電話,你跟他說說具體情況,不一會兒老王把你的代碼給改了改,給你發了回來。
class Attr(object): def __init__(self, name, type_): self.name = name self.type_ = type_ def __get__(self, instance, owner): return instance.__dict__[self.name] def __delete__(self, instance): del instance.__dict__[self.name] def __set__(self, instance, value): if not isinstance(value, self.type_): raise TypeError('expected an %s' % self.type_) if self.name == 'score' and value < 0: raise ValueError('score can not be negative') instance.__dict__[self.name] = value class MovieVoted(object): score = Attr('score', int) title = Attr('title', str) actor = Attr('actor', str) def voted(self, value): return {'title': self.title, 'score': self.score, 'actor': self.actor} m1 = MovieVoted() m1.title = 'xxx' m1.actor = '蒼井空' m1.score = 10 #m1.score = -10 #這時候會報錯
不愧是見過世面的人,一下子就寫出來。不過有很多東西你都沒見過,這時候老王給你耐心解釋。你原來的程式不行是因為你定義的類,對於實例的變數是沒有任何限制的,可以賦值為
任意類型,也可以賦值為任意大小。分數可以賦值為str類型的,當然也可以賦值為負數。現在你需要做的是對實例變數賦值的時候加上一定的條件。python在這方面提供了一個很好的功能
即描述符。你看到函數中出現的__get__、__set__、__delete__就是描述符函數。下麵分別給你解釋一下。
1def __get__(self, instance, owner):
這個函數將會在查詢值的時候被觸發,即print(m1.title) 的時候。instance,owner是它自動會接收的兩個參數,instance即m1這個實例,owner即instance所屬的類,即MovieVoted.這個函數被觸發
通過實例內置方法__dict__[self.name]的方法將值查詢到,並且返回。
2.def __set__(self, instance, value):
這個函數將會在設定值的時候被觸發,instance代表著當前實例,即m1,value代表著設定的值即'蒼井空'。首先判斷value的值是否屬於預先設定的類型,即self.type_這裡預先設定的是 str類型。如果不屬於
就會觸發TypeError,這裡加了一層限制,title的值只能為字元串,有點像靜態語言,事先將一個變數的類型固定下來。如果類型沒有問題,再判斷是不是'score',如果是,並且數字小於0,即觸發一個ValueError.
3.def __delete__(self, instance):
這個和__get__很像,在刪除屬性的時候被觸發,比如del m1.title的時候就會觸發。
這裡面有一個需要註意的地方是,實例一開始並沒有初始化變數。而統一用的都是類裡面的變數,千萬不要把類變數放到初始化函數裡面哦。放進去雖然能正常運行,但是就起不到描述符的作用了。
不愧是見過世面的人,你對老王的崇拜之情又進一步加強了,並且約好了下一再一起去東莞。