12 | 面向对象(下):如何实现一个搜索引擎?
该思维导图由 AI 生成,仅供参考
“高大上”的搜索引擎
- 深入了解
- 翻译
- 解释
- 总结
本文介绍了如何使用面向对象的程序设计思想来实现一个简单的Python搜索引擎。文章首先介绍了搜索引擎的核心构成,包括搜索器、索引器、检索器和用户接口,并解释了它们的功能和作用。接着,文章展示了一个基础的搜索引擎实现,通过继承SearchEngineBase基类,实现process_corpus和search接口,以及使用SimpleEngine子类来实现搜索功能。作者还提出了对这种简单实现方式的低效性和局限性,并提出了优化思路,即对语料进行分词处理,以提升存储和搜索效率。 随后,文章介绍了词袋模型(Bag of Words)和倒序索引(Inverted Index)的搜索模型。通过代码示例展示了如何实现这两种模型,并对它们的优缺点进行了讨论。特别是倒序索引模型的实现,通过对单词建立倒序索引,大大提高了搜索效率,避免了遍历所有ID的尴尬局面。 最后,文章讨论了缓存和多重继承的内容。通过引入LRU缓存和多重继承的方式,对搜索引擎进行了性能优化,提高了重复性搜索的效率。 整体而言,本文通过清晰的代码示例和解释,帮助读者了解了搜索引擎的基本原理和面向对象的程序设计思想,并引发了对搜索引擎实现的优化思考。文章内容涵盖了搜索引擎的基本原理、优化方法以及性能提升的实现方式,对于想要深入了解搜索引擎实现和优化的读者具有很高的参考价值。
《Python 核心技术与实战》,新⼈⾸单¥59
全部留言(88)
- 最新
- 精选
- Jingxiao置顶思考题答案: John Si 的评论说的很对,如果想要强行访问父类的私有类型,做法是 self._ParentClass__var,这是非常不推荐的 hacky method。以下是示范代码: class A: __a = 1 class B(A): pass b = B() print(b._A__a)2019-06-09330
- 小侠龙旋风和面向对象无关的关键词整理: 1.一个搜索引擎由搜索器、索引器、检索器和用户接口四个部分组成。 2.Bag of Words Model,词袋模型。 3.Inverted Index Model,倒序索引。 4.语料corpus分词,齐夫定律。 5.合并 K 个有序数组。 6.LRU缓存。 难点消化:4,5,6 思考题: Python并没有真正的私有化支持,但可用下划线得到伪私有: (1)_xxx "单下划线 " 开始的成员变量叫做保护变量,意思是只有类对象和子类对象自己能访问到这些变量,需通过类提供的接口进行访问; (2)__xxx 类中的私有变量/方法名,只有类对象自己能访问,连子类对象也不能访问到这个数据。 (3)__xxx__ 魔法函数,前后均有一个“双下划线” 代表python里特殊方法专用的标识,如 __init__() 代表类的构造函数。
作者回复: 👍
2019-06-08244 - shiziwen第二种方法,对于多重继承,如果有多个构造函数需要调用, 我们必须用传统的方法LRUCache.__init__(self) 。 这里的两句话没有很明白,LRUCache为什么必须使用第二种方法?
作者回复: super().__init__() 只能调用第一个父类的构造函数,但对于多重继承,如果你想调用其他父类的构造函数,则必须指定。
2020-04-04518 - 及時行樂看到这,我发现我五十元买的课程简直血赚!!!看条评论说看不懂不睡觉,建议你善良删除,我直接被你搞的睡衣全无,感觉能战到天亮
作者回复: 哈哈谢谢支持
2020-04-2928 - 头像我老婆class BOWInvertedIndexEngineWithCache(BOWInvertedIndexEngine, LRUCache): def __init__(self): super(BOWInvertedIndexEngineWithCache, self).__init__() LRUCache.__init__(self) 老师,这里这2种调用父类构造方法不应该是二选一吗,如果这样写的话LRUCache的构造方法会被调用2次 class A(): def __init__(self): print('enter A') print('leave A') class B(A): def __init__(self): print('enter B') super().__init__() print('leave B') class C(A): def __init__(self): print('enter C') super().__init__() print('leave C') class D(B, C): def __init__(self): print('enter D') super(D,self).__init__() C.__init__(self) print('leave D') D() 输出结果: enter D enter B enter C enter A leave A leave C leave B enter C enter A leave A leave C leave D
作者回复: 事实上,你的例子(菱形继承)中确实会出现这个问题,但是如果你再读仔细一些,我的代码等价于: class A(): def __init__(self): print('enter A') print('leave A') class B(A): def __init__(self): print('enter B') super().__init__() print('leave B') class C(): def __init__(self): print('enter C') # super().__init__() print('leave C') class D(B, C): def __init__(self): print('enter D') super(D, self).__init__() C.__init__(self) print('leave D') D() 输出: enter D enter B enter A leave A leave B enter C leave C leave D 不会出现重复 init
2020-03-2237 - quanxyunPython并没有真正的私有化支持,但可用下划线得到伪私有: (1)_xxx "单下划线 " 开始的成员变量叫做保护变量,意思是只有类对象和子类对象自己能访问到这些变量,需通过类提供的接口进行访问; (2)__xxx 类中的私有变量/方法名,只有类对象自己能访问,连子类对象也不能访问到这个数据。 (3)__xxx__ 魔法函数,前后均有一个“双下划线” 代表python里特殊方法专用的标识,如 __init__() 代表类的构造函数。
作者回复: 👍
2019-11-143 - 响雨私有属性不可以被继承,但是可以创建一个普通的方法,在方法中操作私有属性。因为普通的方法是可以操作的。
作者回复: 嗯嗯
2019-06-252 - Claywoow老师可以拓展一下元类吗,它是面向对象编程中一个重要的类型吗?
作者回复: metaclass 作为独立的一章会出现在进阶课程中,敬请期待
2019-06-08 - 益达看不懂不睡觉2019-06-05976
- Wing·三金思考题:子类继承父类私有变量的方法 - 通过定义 get/set 函数来间接操作私有变量 - 通过 实例名._父类名__私有变量名 来直接调用,所以事实上 python 并不直接私有变量 # 主要知识点 - 搜索引擎的四个组成部分 - 迭代开发的流程 - 类的继承与父类函数的强行调用 - 词袋模型 + 逆序索引 + 合并有序数组 = 优化检索速度 + 考虑单词顺序与间隔 - pylru 的基本用法 - 多重继承的初始化规则 # 搜索引擎 - 搜索器:相当于爬虫 - 索引器:为每个文件/网页建立唯一的索引 - 检索器:高效地检索并返回匹配的文件/网页 - 用户接口:输入框和结果返回界面 # 迭代开发的流程 - 构建一个通用的基本框架 - 从最简单的情况考虑起,搭建一个能运行的极简版本 - 按照实际需要不断对具体的实现过程进行优化:如在本讲的例子中,先考虑了单个搜索词 + 小搜索量的情况,构建了 ver 1;然后考虑了多个搜索词,构建了词袋的 ver 2;再考虑了大搜索量,构建了词袋 + 逆序索引的 ver 3(提了 搜索词排序与间隔 情况下的处理思路);最后考虑了负载与重复性搜索问题,构建了使用 LRU 缓存策略的 ver 4 - 如果回过头来看最初的框架,还能发现 add_corpus 的方法并不适用于文件较大的情况,结合前面第六讲的内容可以做些改进;以及 main 函数直接用了 for 循环来找所有的文件,实际使用时用的是诸如 os.walk 的方法2019-06-05165