我曾經(jīng)是一個對Java非常反感的人诱渤,因為Java的語法非常啰嗦蚌铜。而用慣了動態(tài)類型的Python再使用靜態(tài)類型的Java就會覺得多出了很多的工作量。
因為工作的關(guān)系饺谬,我開始使用Java來做項目捂刺。在這個過程中,我發(fā)現(xiàn)Java在某些方面確實和Python不一樣。
有一句話說的好:
語言決定了世界觀族展。
當我Java用的越來越多的時候森缠,我漸漸發(fā)現(xiàn)我不是那么討厭它了。
今天我要講的仪缸,是我從Java里面學到的贵涵,一個被稱為JavaBeans的東西。
In computing based on the Java Platform, JavaBeans are classes that encapsulate many objects into a single object (the bean). They are serializable, have a zero-argument constructor, and allow access to properties using getter and setter methods.
一句話概括起來: 當一些信息需要使用類似于字典套字典套列表這種很深的結(jié)構(gòu)來儲存的時候恰画,請改用類來儲存宾茂。
在Python里面,我以前會寫這樣的代碼:
person_list = [{
'name': 'kingname',
'age': 23,
'sex': 'male'
'detail': {
'address': 'xxx',
'work': 'engineer',
'salary': 100000
}
},
{
'name': 'xiaoming',
'age': 65,
'sex': 'male'
'detail': {
'address': 'yyy',
'work': 'pm',
'salary': 0.5
}
}]
由于Python動態(tài)類型的特點拴还,字典里面的value經(jīng)常是包含了各種類型刻炒,有時候,字典里面包含了字典自沧,里面的字典里面還有列表,這個內(nèi)部字典里面的列表里面又包含了字典……
當我剛剛開始寫Java代碼的時候树瞭,也會保留了這個壞習慣拇厢,于是我定義的一個變量類似于這樣:
public Map<String, List<Map<String, Map<String, Object>>>> info = .....
并且由于Java是靜態(tài)類型語言,有時候Map里面的Value類型還不一致晒喷,需要使用Object來代替孝偎,等要使用的時候再做類型轉(zhuǎn)換。
對于這樣的寫法凉敲,真可謂是寫代碼一時爽衣盾,調(diào)試代碼火葬場。我過幾天讀自己的代碼爷抓,自己都不知道這個字典里面有哪些內(nèi)容势决,也不知道它們有哪些類型,必須到定義的地方去看蓝撇。
我的Mentor看了我的Java代碼以后果复,讓我去用一下JavaBeans,于是我的世界瞬間就簡潔多了渤昌。后來我將JavaBeans的思想用到Python中虽抄,果然Python代碼也變得好看多了。
使用上面person_list這個復雜的結(jié)構(gòu)為例独柑,我用JavaBeans的思想迈窟,在Python里面重構(gòu)它:
class Person(object):
def __init__(self, name='', age=0, sex='', detail=None):
self._name = name
self._age = age
self._sex = sex
self._detail = detail
@property
def name(self):
return self._name
@name.setter
def name(self, new_name):
self._name = new_name
@property
def age(self):
return self._age
@age.setter
def age(self, new_age):
self._age = new_age
@property
def sex(self):
return self._sex
@sex.setter
def sex(self, new_sex):
self._sex = new_sex
@property
def detail(self):
return self._detail
@detail.setter
def detail(self, new_detail):
self._detail = new_detail
class Detail(object):
def __init__(self, address='', work='', salary=0):
self._address = address
self._work = work
self._salary = salary
@property
def address(self):
return self._address
@address.setter
def address(self, new_address):
self._address = new_address
@property
def work(self):
return self._work
@work.setter
def work(self, new_work):
self._work = new_work
@property
def salary(self):
return self._salary
@salary.setter
def salary(self, new_salary):
self._salary = new_salary
從這里可以看到,我把字典變成了類忌栅。于是车酣,當我想保存我自己的信息和小明的時候,我就可以這樣寫:
detail_kingname = Detail(address='xxx', work='engineer', salary=10000),
kingname = Person(name='kingname', age=23, sex='male', detail=detail_kingname)
detail_xiaoming = Detail(address='yyy', work='pm', salary=0.5),
xiaoming = Person(name='xiaoming', age=65, sex='male', detail=detail_xiaoming)
person_list = [kingname, xiaoming]
這樣寫,雖然說代碼量確實翻了不止一倍骇径,但是當我們后期維護的時候或者遇到問題來調(diào)試代碼躯肌,我們就能發(fā)現(xiàn)這樣寫的好處。
舉一個很簡單的例子破衔,在寫了代碼一年以后清女,我已經(jīng)對這段代碼沒有多少印象了,現(xiàn)在我得到了變量person_list
, 我想查看每個人的工資晰筛。首先嫡丙,由于Person
和Detail
這兩個類是已經(jīng)定義好的,分別放在Person.py
和Detail.py
兩個文件中读第,于是我點開它們曙博,就知道,原來工資是保存在Detail
這個類中的怜瞒,關(guān)鍵詞是salary
, 而Detail
又是保存在Person
中的父泳,關(guān)鍵詞是detail
。
所以要查看每個人的工資吴汪,我可以這樣寫:
for person in person_list:
detail = person.detail
salary = detail.salary
print(salary)
但是如果我使用的是最上面字典的那種方式惠窄,那么情況就沒有這么簡單了。因為我不知道工資是在這個字典的什么地方漾橙。于是我首先要找到person_list
是在哪里初始化的杆融,然后看它里面有什么。在這個例子中霜运,我是一次性把整個列表字典初始化完成的脾歇,直接找到列表初始化的地方就知道,原來這個person_list
下面有很多個字典淘捡,字典有一個key 叫detail
,這個detail
的value本身又是一個字典藕各,它下面的keysalary
保存了工資的信息。這似乎還比較方便焦除。但是如果字典里面的信息不是一次性初始化完成的呢座韵?萬一detail
這一個key是后面再加的呢?于是又要去找detail
初始化的地方……
第二個好處踢京,使用Beans的時候誉碴,每個關(guān)鍵字是定義好的,salary
就只能叫做salary
瓣距,如果寫成了salarv
, 集成開發(fā)環(huán)境會立刻告訴你黔帕,Detail
沒有salarv
這個屬性。但是如果使用字典的方式蹈丸,我在給字典賦值的時候成黄,一不小心:
detail['salarv'] = 0.5
由于這里的salarv
是字符串呐芥,所以集成開發(fā)環(huán)境是不會報錯的,只有等你運行的時候,嘗試讀取detail['salary']
里面的值奋岁,Python會告訴你:
Traceback (most recent call last):
File "xxx.py", line 1, in <module>
KeyError: 'salary'
總結(jié)
將JavaBeans的思想用在Python中思瘟,避免字典套字典這種深層嵌套的情況,對于一些需要反復使用的字典闻伶,使用類來表示滨攻。這樣做,別人讀代碼的時候會更加的容易蓝翰,自己開發(fā)的時候光绕,也會避免出現(xiàn)問題。
本文首發(fā)地址: http://kingname.info/2016/06/19/bean-in-python/ 轉(zhuǎn)載請注明出處畜份。