2

我有一个名为 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

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

4

4 回答 4

2

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

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

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

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

于 2012-06-12T19:30:56.473 回答
2

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

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

归根结底,这一切都取决于在应用程序中对 Video 对象所做的事情。

于 2012-06-12T19:33:13.777 回答
1

延迟评估(或延迟加载,或延迟初始化)在后续操作需要对后端进行更多查询时,或者当请求非常大以至于分块执行时很有用,或者当有很好的机会时你不会使用请求的每个部分...一般来说,它是在急切行为(例如range()在 Python 2.x 中)和懒惰行为(range()在 Python 3.x 中)之间进行选择。

在这种情况下,似乎无论如何使用视频对象,最终都会发生对单个对象的 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 库……),但这就是它的要点。

于 2012-06-12T19:33:38.783 回答
0

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

实现您使用的惰性评估类型并避免代码复杂性的一种方法是在金字塔库中使用像 @reify 这样的装饰器。查看此博客条目中金字塔库中的 @reify 装饰器,其中包含底部的 reify 源链接

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

于 2012-06-12T19:36:41.730 回答