【问题标题】:How to not return object reference from __init__如何不从 __init__ 返回对象引用
【发布时间】:2018-11-05 11:53:31
【问题描述】:

我是 ItemLoaders 的新手。 我有一个集合seen_ids,我在其中添加了我抓取的所有product_ids,以便我可以检查是否有任何重复并尽早跳过它。

问题是,我想在__init__ 中执行此操作。如果它是重复的,我不希望返回任何引用,并且我不能从 __init__ 显式返回 None。我该怎么做?

seen_ids = set()

def __init__(self, item=None, selector=None, response=None, parent=None, product_id=None, **context):
    if product_id in self.seen_ids:
        return None

    self.seen_ids.add(product_id)
    super(GarmentLoader, self).__init__(item, selector, response, parent, **context)
    item['retailer_sku'] = product_id

但它在 None 上给出错误,如果我不返回任何内容,它会返回对象的引用并且进一步检查失败。

【问题讨论】:

  • 这不是您应该在__init__ 级别处理的事情,而是在__new__ 级别处理。
  • 此外__init__的值无关紧要,python中的大多数__init__s不返回任何东西
  • 具体来说,__init__ 采用__new__ 返回的值并将__init__ 中指定的任何指令应用于该值; __init__ 返回的任何值都将被丢弃。
  • 实例创建是否相同?? garment_loader = GarmentLoader(item=Garment(), response=response, product_id=product_id) 像这样??我将如何访问 new 中的 product_id ??
  • 此外,对象构造返回对象的唯一方法是抛出错误。如果Foo() 返回None,我会感到非常惊讶。暂时可能不完全重复但有用:Memoized objects still have their __init__() invoked?

标签: python scrapy scrapy-item


【解决方案1】:

这是行不通的,因为构造函数基本上只返回实例之外的任何东西,而且实例不会共享 seen_ids。

你可以使用类方法来代替:

class CustomItemLoader(ItemLoader):
    seen_ids = set()

    @classmethod
    def with_product_id(cls, **kwargs):
        product_id = kwargs.pop('product_id', None)
        if product_id in cls.seen_ids:
            return None
        cls.seen_ids.add(product_id)
        return cls(**kwargs)

然后使用它创建加载器的实例:

loader = CustomItemLoader.with_product_id(response=response, product_id=product_id, ...)

【讨论】:

    猜你喜欢
    • 2023-01-04
    • 1970-01-01
    • 1970-01-01
    • 2020-08-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-27
    • 1970-01-01
    相关资源
    最近更新 更多