将一个类的特性组合到另一个类的最合适的方法是什么?

2024-04-24 16:54:54 发布

您现在位置:Python中文网/ 问答频道 /正文

嘿,伙计们,我是新来的,但希望我的问题是清楚的。你知道吗

我的代码是用Python编写的。 我有一个表示一般网站的基类,这个类包含一些从网站获取数据并保存数据的基本方法。该类由许多其他类扩展,每个类表示一个不同的网站,每个类持有该网站的特定属性,每个子类使用基类方法获取数据。所有站点都应该在其上解析数据,但许多站点共享相同的解析功能。因此,我创建了几个解析类,其中包含不同解析方法的功能和属性(我有大约六个)。我开始思考,将这些类与需要它们的网站类集成的最佳方式是什么。你知道吗

一开始我以为每个网站类都会包含一个类变量和对应的解析器类,但后来我想一定有更好的方法来实现它。你知道吗

我读了一点书,认为我最好依靠Mixin来集成每个网站的解析器,但后来我想,虽然这样做是可行的,但它并不“听起来”正确,因为website类没有业务继承自parser类(甚至认为它只是一个Mixin,并不意味着是一个完整的类继承),因为它们除了网站使用解析器功能外,其他方面都不相关。你知道吗

然后我想我可能会依赖于python的依赖注入代码来将解析器注入到每个网站,但这听起来有点过分了。你知道吗

所以我想我的问题基本上是,什么时候最好使用每个案例(在我的项目和任何其他项目中),因为他们都做了工作,但似乎不是最合适的。你知道吗

谢谢你的帮助,我希望我说的很清楚。你知道吗

添加一个小的模拟示例来说明:

class BaseWebsite():
    def fetch(): # Shared by all subclasses websites
       ....
    def save(): # Shared by all subclasses websites
       ....

class FirstWebsite(BaseWebsite): # Uses parsing method one
    ....
class SecondWebsite(BaseWebsite): # Uses parsing method one
    ....
class ThirdWebsite(BaseWebsite): # Uses parsing method two
    ....

等等


Tags: 数据方法代码功能解析器属性站点网站
1条回答
网友
1楼 · 发布于 2024-04-24 16:54:54

我认为你的问题是你在使用子类,而你应该使用实例。你知道吗

根据你的描述,每个网站有一个类,有一堆属性。假设您创建了每个类的单例实例。在Python中很少有好的理由这么做。如果每个网站需要不同的数据—一个基本URL、一个解析器对象/工厂/函数等等—您可以将其存储在实例属性中,这样每个网站都可以是同一类的实例。你知道吗

如果网站真的需要,比如说,以不同的方式重写基类方法,那么它们是不同的类是有意义的(尽管如此,您应该考虑是否将该功能移动到网站可以使用的外部函数或对象中,就像您已经使用解析器一样)。但如果不是,就没有理由这么做。你知道吗

当然,我在这里可能是错的,但是您定义了旧式的类,将self参数留在了方法之外,讨论了类属性,并且通常使用Java术语而不是Python术语,这一事实使我认为这个错误的可能性不大。你知道吗

换句话说,你想要的是:

class Website:
    def __init__(self, parser, spam, eggs):
        self.parser = parser
        # ...
    def fetch(self):
        data = # ...
        soup = self.parser(data)
        # ...

first_website = Website(parser_one, urls[0], 23)
second_website = Website(parser_one, urls[1], 42)
third_website = Website(parser_two, urls[2], 69105)

假设你有20个网站。如果你要创建20个子类,你要为每个子类编写6行样板文件,在细节上你可能会犯很多错误,调试起来可能会很痛苦。如果您要创建20个实例,那么这只是样板文件中的几个字符,出错的可能性要小得多:

websites = [Website(parser_one, urls[0], 23),
            Website(parser_two, urls[1], 42),
            # ...
           ]

或者您甚至可以将数据移动到数据文件中。例如,像这样的CSV:

url,parser,spam
http://example.com/foo,parser_one,23
http://example.com/bar,parser_two,42
…

您可以更容易地编辑它,甚至可以使用电子表格程序来完成它,而不需要任何额外的键入。您可以通过几行代码将其导入到Python中:

with open('websites.csv') as f:
    websites = [Website(**row) for row in csv.DictReader(f)]

相关问题 更多 >