1 Why Class
(這篇文章是一篇新手級的文章啃匿,請高手繞道)
最初人們編程的時候都是用過程在編程露筒。然而隨著使用的深入断部,人們開始使用類仿粹。大概的進(jìn)化過程是這樣:
過程—> 過程+函數(shù) —> 類 —> 類&子類......
我們作為一個初學(xué)者的時候,往往不明白為什么要用類崭添,為什么不直接用過程就好了寓娩。Well, 簡短的程序是可以用過程+函數(shù),然而一旦要涉及到很多調(diào)用的情況,還是要有Class棘伴,讓整個程序都可以看起來很清爽寞埠。
2 Class is an abstract of things
下面舉一個例子:
Al在它的書里面第八章[https://automatetheboringstuff.com/chapter8/] 講了一個project(Project: Generating Random Quiz Files),就是講的一個有一個地理老師焊夸,他管理了一個35人的班級仁连,準(zhǔn)備給他們出一套試題,考考美國的50個州和每個州的首府阱穗;由于有很多童鞋喜歡抄襲饭冬,所以這個老師就準(zhǔn)備每個學(xué)生準(zhǔn)備一份(美國老師好敬業(yè)啊,遙想讀書當(dāng)年揪阶,我們的老師最多就提過AB卷)昌抠,然而如果人工來準(zhǔn)備太麻煩了,所以老師決定自動化遣钳。
要解決的思路很簡單扰魂,就是通過幾個循環(huán)麦乞,將答案shuffle開就是蕴茴,這里寫一段偽代碼講講大致思路:
for 童鞋 = 1 to 童鞋總數(shù)(35):
隨機(jī)打亂50題
for 每一題 = 1 to 題目總數(shù)(50):
生成正確的答案+錯誤的答案
打印問題到試卷文件中
打印答案到答案文件中
具體思路請看Al的帖子[https://automatetheboringstuff.com/chapter8/] ,搜索Generating Random Quiz Files姐直。
新的問題
那么現(xiàn)在問題來了倦淀,如果是有一個中國的地理老師是你的朋友,準(zhǔn)備跟國際接軌声畏,考中國的34個省的省會撞叽,而班上有60位同學(xué),你也準(zhǔn)備每人準(zhǔn)備一套試卷插龄,要怎么準(zhǔn)備呢愿棋?
有一個簡單的方法就是改參數(shù),然而均牢,這樣的問題是糠雨,可能而且程序也會顯得很ad-hoc。如果又是另一個國家的又怎么辦徘跪。如果這個地理老師下次再找到你甘邀,讓你幫忙給班上58位同學(xué)準(zhǔn)備有48道題的試卷呢?
3 Class Solution
所以這里提出類的方法垮庐。聽過類的童鞋都知道類有『封裝松邪,繼承,多態(tài)』三個屬性哨查。咱們這里會用到封裝逗抑。
這里是將Al的方法改為Class之后的結(jié)果:
# -- coding: utf-8 --# RandomQuizGenerator.pyimport randomcapitals = {'Alabama': 'Montgomery', 'Alaska': 'Juneau', 'Arizona': 'Phoenix', 'Arkansas': 'Little Rock', 'California': 'Sacramento', 'Colorado': 'Denver', 'Connecticut': 'Hartford', 'Delaware': 'Dover', 'Florida': 'Tallahassee', 'Georgia': 'Atlanta', 'Hawaii': 'Honolulu', 'Idaho': 'Boise', 'Illinois': 'Springfield', 'Indiana': 'Indianapolis', 'Iowa': 'Des Moines', 'Kansas': 'Topeka', 'Kentucky': 'Frankfort', 'Louisiana': 'Baton Rouge', 'Maine': 'Augusta', 'Maryland': 'Annapolis', 'Massachusetts': 'Boston', 'Michigan': 'Lansing', 'Minnesota': 'Saint Paul', 'Mississippi': 'Jackson', 'Missouri': 'Jefferson City', 'Montana': 'Helena', 'Nebraska': 'Lincoln', 'Nevada': 'Carson City', 'New Hampshire': 'Concord', 'New Jersey': 'Trenton', 'New Mexico': 'Santa Fe', 'New York': 'Albany', 'North Carolina': 'Raleigh', 'North Dakota': 'Bismarck', 'Ohio': 'Columbus', 'Oklahoma': 'Oklahoma City', 'Oregon': 'Salem', 'Pennsylvania': 'Harrisburg', 'Rhode Island': 'Providence', 'South Carolina': 'Columbia', 'South Dakota': 'Pierre', 'Tennessee': 'Nashville', 'Texas': 'Austin', 'Utah': 'Salt Lake City', 'Vermont': 'Montpelier', 'Virginia': 'Richmond', 'Washington': 'Olympia', 'West Virginia': 'Charleston', 'Wisconsin': 'Madison', 'Wyoming': 'Cheyenne'}NUM_OF_STUDENTS = 35NUM_OF_QUESTIONS = 50class RandomQuizGenerator(): def __init__(self, capitals, number_of_students, number_of_questions): self.capitals = capitals self.number_of_students = number_of_students self.number_of_questions = number_of_questions self.quiz_file = None self.quiz_answer_file = None def run(self): # TODO create a loop of number_of_students quizzes for quiz_num in range(self.number_of_students): # Create the quiz and answer key files. self.init_quiz_file(quiz_num) # Generate random questions' order for each quiz. unique_states_list = list(self.capitals.keys()) random.shuffle(unique_states_list) # loop through all 50 States, making a question for each. self.generate_one_quiz(unique_states_list) # Close the quiz_file and the quiz_answer_file self.close_quiz_file() def init_quiz_file(self, quiz_num): self.quiz_file = open('capitalsQuiz%s.txt' % (quiz_num + 1), 'w') self.quiz_answer_file = open('capitalsQuiz_Answers%s.txt' % (quiz_num + 1), 'w') # Write out the header for the quiz. self.quiz_file.write('Name:\n\nDate:\n\nPeriod:\n\n') self.quiz_file.write((' ' * 20) + 'States Capitals Quiz (Form %s)' % (quiz_num + 1)) self.quiz_file.write('\n\n') def close_quiz_file(self): self.quiz_file.close() self.quiz_answer_file.close() def generate_one_quiz(self, unique_states_list): for question_num in range(self.number_of_questions): # Generate wrong answers question_state = unique_states_list[question_num] correct_answer = self.capitals[question_state] wrong_answers = list(self.capitals.values()) del wrong_answers[wrong_answers.index(correct_answer)] wrong_answers = random.sample(wrong_answers, 3) # Get the right answer and mingle with the wrong one answer_options = wrong_answers + [correct_answer] random.shuffle(answer_options) # Write the answer to the self.quiz_file self.quiz_file.write('%s. What is the capital of %s?\n' % (question_num + 1, question_state.encode('utf-8'))) for i in range(4): self.quiz_file.write(' %s. %s\n' % ('ABCD'[i], answer_options[i].encode('utf-8'))) self.quiz_file.write('\n') # Write the answer to the self.quiz_answer_file self.quiz_answer_file.write('%s. %s\n' % (question_num + 1, 'ABCD'[answer_options.index(correct_answer)])) def change_save_file_name(self, quiz_save_name, answer_save_name): # TODO The teacher can change the name of the save file. passdef main(): random_quiz_generator = RandomQuizGenerator(capitals, NUM_OF_STUDENTS, NUM_OF_QUESTIONS) random_quiz_generator.run() passif __name__ == '__main__': main()
¥¥¥¥¥¥¥¥¥¥¥我是文件的分界線¥¥¥¥¥¥¥¥¥¥
封裝
你可能會說,這個看著比原來更復(fù)雜啊,然而邮府,假如這個是拿給地理老師浙于,他并不需要懂上面那一段,他只需要看懂下面這段代碼就是了:
# -- coding: utf-8 --
# china_provincial_capital.py
import RandomQuizGenerator
capitals = {u'北京': u'北京', u'上海': u'上海', u'天津': u'天津', u'重慶':u'重慶', u'新疆': u'烏魯木齊',
u'黑龍江': u'哈爾濱', u'吉林': u'長春', u'遼寧': u'沈陽', u'內(nèi)蒙古': u'呼和浩特', u'河北': u'石家莊',
u'甘肅': u'蘭州', u'青海': u'西寧', u'陜西': u'西安', u'寧夏': u'銀川', u'河南': u'鄭州',
u'山東': u'濟(jì)南', u'山西': u'太原', u'安徽': u'合肥', u'湖北': u'武漢', u'湖南': u'長沙',
u'江蘇': u'南京', u'四川': u'成都', u'貴州': u'貴陽', u'云南': u'昆明', u'廣西': u'南寧',
u'西藏': u'拉薩', u'浙江': u'杭州', u'江西': u'南昌', u'廣東': u'廣州', u'福建': u'福州',
u'臺灣': u'臺北', u'海南': u'盒矗口', u'香港': u'香港', u'澳門': u'澳門'
}
if __name__ == '__main__':
total_question = len(capitals)
total_students = 6
china_capital_quiz = RandomQuizGenerator.RandomQuizGenerator(capitals, total_students, total_question)
china_capital_quiz.run()
是不是要清爽很多羞酗?但為什么這么短呢?因為你把題目封裝了紊服,封裝將詳細(xì)的方法隱藏了檀轨,所以Class只需要被調(diào)用就是;具體的實現(xiàn)欺嗤,只需要操作一個很小的文件就是了参萄。
繼承、多態(tài)
可能有同學(xué)會說:『我用過程去改一下輸入輸出也可以做這件事哦』煎饼。嘿嘿讹挎,好像是可以;然而假如你面對的不是一個地理老師呢吆玖?如果是還有其他老師筒溃,選擇題的選項不止4個怎么辦?又拿原來做好的過程文件去改沾乘;還是用Class中拉一個subclass出來呢怜奖?很明顯答案是subclass更好。首先可以繼承原來的Class翅阵,然后還可以在這個Class上做改變歪玲。整個程序也會更清晰。
4 Conclusion
所以咯掷匠,學(xué)習(xí)Class滥崩,有一個方法就是把自己原來寫的那些過程改一下,這樣可以更好的體驗喲