Python 这是否是惰性评估的合理用例?

Python 这是否是惰性评估的合理用例?,python,youtube-api,Python,Youtube Api,我有一个名为Video的python类,它表示YouTube视频。给定YouTube视频的ID,video返回表示该视频的对象。但是,首次创建视频对象时,不会查询YouTube。YouTube仅在请求需要来自YouTube的信息的属性时才被查询。下面是它的工作原理: >>> from video import Video >>> video = Video('B11msns6wPU') # 'B11msns6wPU' is the ID of a video

我有一个名为Video的python类,它表示YouTube视频。给定YouTube视频的ID,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

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

这是一种一般性的判断,而不是一个艰难而快速的决定

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

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


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

这是
延迟加载。如果这些属性并不总是需要的话,那么实现这些属性是值得的,并且从api中查询它们是一种浪费。与中一样,我创建了一个
Video
类,但我不需要这些属性

当获取/加载类属性需要很长时间时,延迟加载是一个好主意。那么,在您的例子中,API调用是否昂贵,您的
视频类是否真的需要它?关于视频类的更多信息将有助于了解它是否值得实现。延迟加载只是为了延迟加载而增加了代码的复杂性,这并没有什么好的理由,所以是的,看看是否需要延迟加载是很重要的

归根结底,这一切都取决于您在应用程序中如何处理视频对象

(或,或)在后续操作需要对后端进行更多查询时,或当请求太大以至于需要分块执行时,或当您很有可能不使用请求的每个部分时非常有用。。。一般来说,它是在渴望行为(例如Python 2.x中的
range()
)和懒惰(Python 3.x中的
range()
)之间的选择

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

是的,您正在实施延迟评估,正如对“值得吗”问题的其他答案一样,这取决于数据的使用模式以及您希望让用户等待的时间。需要记住的另一件事是,如果提取视频数据可能需要一段时间,但您相当确定您将需要数据,那么您可以在另一个执行线程中提取数据以预取数据

实现您所使用的延迟计算类型并避免代码中的复杂性的一种方法是在金字塔库中使用类似@reify的修饰符。在这张图片中,看看金字塔库中的@reify decorator


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

您选择这样做的原因是什么?