【问题标题】:Would this be a reasonable use-case for lazy evaluation?这会是惰性评估的合理用例吗?
【发布时间】:2012-06-12 19:19:54
【问题描述】:

我有一个名为 Video 的 python 类,它代表 YouTube 视频。给定 YouTube 视频的 ID,Video 返回一个表示该视频的对象。但是,当第一次创建 Video 对象时,不会查询 YouTube。仅当要求提供需要来自 YouTube 的信息的属性时才会查询 YouTube。以下是它的工作原理:

>>> from video import Video
>>> video = Video('B11msns6wPU') 
# 'B11msns6wPU' is the ID of a video
>>> video
Video(youtube_id="B11msns6wPU")
### As of now, no call to YouTube's API has been made
### Next, I ask for the title attribute. The object queries YouTube's API to get 
### this information. In doing so, the object is completely initialized
>>> video.title
u'Badly Drawn Boy - Disillusion (directed by Garth Jennings)'
>>> video.duration
u'275'
# no query was made to the API because the object has been already been initialized

我不确定这是否是技术上的“懒惰评估”,但它的风格相似。在第一次调用属性之前,不会初始化视频对象。我想知道这种技术是否值得实施。显然,它使我的代码更加复杂。你有什么想法?

【问题讨论】:

  • 您选择这样做有什么原因吗?

标签: python youtube-api


【解决方案1】:

这是一种一般性的判断,而不是硬性决定。

如果惰性对象 Video 类实例是您的应用程序的核心,那么在执行其他任何操作之前完全初始化它可能是有意义的;如果您的应用没有数据就没有用,请先获取数据。

但是,如果您的应用程序可能有成百上千个这样的Video 实例,并且其中大部分不会被使用,那么在您初始化它们时让用户等待是没有意义的。在这种情况下,将初始化推迟到真正需要时会很有意义。例如,如果您要显示“缩略图墙”显示,您可能需要每个视频和标题的缩略图,但您可能不需要其他任何内容,除非用户单击缩略图。

我确实喜欢一般的方法,即使用对象的代码不需要知道或关心对象是否已预先初始化。

【讨论】:

    【解决方案2】:

    这是lazy loading。如果这些属性并不总是需要,那么值得实现,并且从 api 查询它们将是一种浪费。如,我创建了一个 Video 类,但我不需要这些属性。

    当类属性需要很长时间来获取/加载时,延迟加载是一个好主意。因此,在您的情况下,API 调用是否昂贵,您的 Video 课程是否真的需要它?有关 Video 类的更多信息将有助于了解它是否值得实施。延迟加载只是为了延迟加载而无缘无故地增加了代码的复杂性,所以是的,看看是否需要延迟加载很重要。

    归根结底,这一切都归结为您对应用程序中的 Video 对象做了什么

    【讨论】:

      【解决方案3】:

      Lazy evaluation(或lazy loading,或lazy initialization)在后续操作需要对后端进行更多查询,或者当请求太大以至于它会被有利于分块进行,或者很有可能您不会使用请求的每个部分...通常,这是在急切行为(例如 Python 2.x 中的range())和懒惰( range() 在 Python 3.x 中)。

      在这种情况下,似乎无论视频对象如何使用,最终都会发生对那个 single 对象的 Youtube API 的调用。

      如果您的库支持更复杂的查询或用法,惰性求值可能非常有用。大致如下:

      >>> video_list = ['B11msns6wPU', 'GuaCaMole', 'OvER9000']
      >>> videos = Video.fetch(video_list)
      # No API call, yet
      >>> videos.filter_by('duration', lambda dur: int(dur) > 200)
      # Filter by duration - still no API call
      >>> for v in videos.all:
      ...     # Now the API call is made, and the filtering is done all at once
      

      当然,我知道我的示例是人为设计的(它看起来很奇怪,像一个 DB 库...),但这就是它的要点。

      【讨论】:

        【解决方案4】:

        是的,您正在实施惰性评估,并且作为“是否值得”这个问题的其他答案,这取决于数据的使用模式以及您何时想让用户等待。要记住的另一件事是,如果提取视频数据可能需要一段时间,但您相当确定您将需要数据,您可以在另一个执行线程中提取数据以预取它。

        实现您使用的惰性求值类型并避免代码复杂性的一种方法是在金字塔库中使用像 @reify 这样的装饰器。看看这个blog entry which contains a link to reify source at the bottom中金字塔库中的@reify 装饰器

        这可能不是您想要的实现方式,但值得一看“pythonic”的惰性求值解决方案。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2014-02-08
          • 2013-03-11
          • 2017-01-18
          • 2018-11-11
          • 2011-01-10
          • 2015-05-29
          相关资源
          最近更新 更多