Welcome to WuJiGu Developer Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
669 views
in Technique[技术] by (71.8m points)

[python]三方库bs4(BeautifulSoup)的对象可以使用任何名字作为属性是怎么实现的?

举例:

from bs4 import BeautifulSoup
fp = open('test.html', encoding='utf-8')
soup = BeautifulSoup(fp, 'lxml')

soup.a # 1
soup.script # 2
soup.div # 3
soup.abcdefg # 4

说明:
soup实例可以使用标签名作为属性,返回封装了test.html中正序第一个该标签内容的bs4.element.Tag对象。

但是我发现属性a、script、div并没有事先定义在类中,并且即便是随便输入的属性名(#4)也不会抛出异常,只是返回一个None。

在我的认知中,对象的属性是需要事先在类中定义、或者动态绑定的,像bs4这样可以直接的使用任意属性名,是怎么实现的?


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

在Python 类里,只要实现以下方法:

  • __getattr__(self, name)
  • __setattr__(self, name, value)
  • __delattr__(self, name)

便可以动态使用属性

请参阅http://docs.python.org/reference/datamodel.html#customizing-attribute-access

__getattr__方法可能如下所示:

def __getattr__(self, name):
    try:
        return self.__dict[name]
    except KeyError:
        msg = "'{0}' object has no attribute '{1}'"
        raise AttributeError(msg.format(type(self).__name__, name))

一个小例子:

class ObjectDict(dict):
    def __init__(self, *args, **kwargs):
        super(ObjectDict, self).__init__(*args, **kwargs)
    def __getattr__(self, name):
        try:
            value = self[name]
            if isinstance(value, dict):
                value = ObjectDict(value)
            return value
        except KeyError:
            return None
if __name__ == '__main__':
    od = ObjectDict(asf={'a': 1}, d=True)
    print(od.asf, od.asf.a)    # {'a': 1} 1
 print(od.d)                 # True
 print(od.x)  # None

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to WuJiGu Developer Q&A Community for programmer and developer-Open, Learning and Share

2.1m questions

2.1m answers

62 comments

56.7k users

...