我刚开始接触爬虫的时候,只是看完了 python 的基础,对 python 的语法尚未一个很深刻的了解,在使用 bs4 这个库的时候,对其中某些语法感到很是的惊奇,不明白是怎么实现的。python
bs4 的官方文档中说到:find_all()
几乎是 Beautiful Soup 中最经常使用的搜索方法,因此咱们定义了它的简写方法。BeautifulSoup
对象和 tag
对象能够被看成一个方法来使用,这个方法的执行结果与调用这个对象的 find_all()
方法相同,下面两行代码是等价的:markdown
soup.find_all("a") soup("a")
这里,soup
是一个 BeautifulSoup
对象,soup("a")
这很明显是把对象当方法使用了,这是怎么作到的呢?ide
在 Python 中,除了用户定义的函数,调用运算符(即 ())还能够应用到其余对象上。内置的 callable()
函数用来判断一个对象可否调用。就是说,任何 Python 对象均可以表现得像函数同样,为此,只需实现实例方法 __call__
。函数
来看一个简单的示例:post
class Sum: def __init__(self, x, y): self._x = x self._y = y def add(self): return self._x + self._y def __call__(self): return self.add() sum = Sum(1, 2) print(sum.add()) print(sum()) print(callable(sum))
输出:code
3 3 True
这样就明白了,bs4 中亦是如此,源码以下:对象
class Tag(PageElement): def __call__(self, *args, **kwargs): return self.find_all(*args, **kwargs)
这背后涉及到的概念叫作可调用对象,Python 数据模型文档列出了 7 种可调用对象。文档
__new__
方法建立一个实例,而后运行 __init__
方法,初始化实例,最后把实例返回给调用方。由于 Python 没有 new
运算符,因此调用类至关于调用函数。(一般,调用类会建立那个类的实例,不过覆盖 __new__
方法的话,也可能出现其余行为。)__call__
方法,那么它的实例能够做为函数调用。