类与封装(Class and Encapsulation) in Python

1 Why Class

(这篇文章是一篇新手级的文章,请高手绕道)
最初人们编程的时候都是用过程在编程。然而随着使用的深入,人们开始使用类。大概的进化过程是这样:

过程—> 过程+函数 —> 类 —> 类&子类......

我们作为一个初学者的时候,往往不明白为什么要用类,为什么不直接用过程就好了。Well, 简短的程序是可以用过程+函数,然而一旦要涉及到很多调用的情况,还是要有Class,让整个程序都可以看起来很清爽。

2 Class is an abstract of things

下面举一个例子:
Al在它的书里面第八章[https://automatetheboringstuff.com/chapter8/] 讲了一个project(Project: Generating Random Quiz Files),就是讲的一个有一个地理老师,他管理了一个35人的班级,准备给他们出一套试题,考考美国的50个州和每个州的首府;由于有很多童鞋喜欢抄袭,所以这个老师就准备每个学生准备一份(美国老师好敬业啊,遥想读书当年,我们的老师最多就提过AB卷),然而如果人工来准备太麻烦了,所以老师决定自动化。

要解决的思路很简单,就是通过几个循环,将答案shuffle开就是,这里写一段伪代码讲讲大致思路:

for 童鞋 = 1 to 童鞋总数(35):
    随机打乱50题
        
for 每一题 = 1 to 题目总数(50):
    
             生成正确的答案+错误的答案
    
             打印问题到试卷文件中
    
             打印答案到答案文件中

具体思路请看Al的帖子[https://automatetheboringstuff.com/chapter8/] ,搜索Generating Random Quiz Files。

新的问题

那么现在问题来了,如果是有一个中国的地理老师是你的朋友,准备跟国际接轨,考中国的34个省的省会,而班上有60位同学,你也准备每人准备一套试卷,要怎么准备呢?

有一个简单的方法就是改参数,然而,这样的问题是,可能而且程序也会显得很ad-hoc。如果又是另一个国家的又怎么办。如果这个地理老师下次再找到你,让你帮忙给班上58位同学准备有48道题的试卷呢?

3 Class Solution

所以这里提出类的方法。听过类的童鞋都知道类有『封装,继承,多态』三个属性。咱们这里会用到封装。
这里是将Al的方法改为Class之后的结果:

# -- 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()

¥¥¥¥¥¥¥¥¥¥¥我是文件的分界线¥¥¥¥¥¥¥¥¥¥

封装

你可能会说,这个看着比原来更复杂啊,然而,假如这个是拿给地理老师,他并不需要懂上面那一段,他只需要看懂下面这段代码就是了:

# -- 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'内蒙古': 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'浙江': 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()

是不是要清爽很多?但为什么这么短呢?因为你把题目封装了,封装将详细的方法隐藏了,所以Class只需要被调用就是;具体的实现,只需要操作一个很小的文件就是了。

继承、多态

可能有同学会说:『我用过程去改一下输入输出也可以做这件事哦』。嘿嘿,好像是可以;然而假如你面对的不是一个地理老师呢?如果是还有其他老师,选择题的选项不止4个怎么办?又拿原来做好的过程文件去改;还是用Class中拉一个subclass出来呢?很明显答案是subclass更好。首先可以继承原来的Class,然后还可以在这个Class上做改变。整个程序也会更清晰。

4 Conclusion

所以咯,学习Class,有一个方法就是把自己原来写的那些过程改一下,这样可以更好的体验哟

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,015评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,262评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,727评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,986评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,363评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,610评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,871评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,582评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,297评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,551评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,053评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,385评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,035评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,079评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,841评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,648评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,550评论 2 270

推荐阅读更多精彩内容