我有一个名为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
我不确定这在技术上是否是“懒惰的评价”,但它的味道相似。在第一次调用属性之前,不会初始化视频对象。我想知道这种技术是否值得实施。显然,它使我的代码更复杂一些。你有什么想法?
答案 0 :(得分:2)
这是一种普遍的判断,而不是一个快速的决定。
如果惰性对象(Video
类实例)是您的应用程序的核心,那么在执行任何其他操作之前完全初始化它可能是有意义的;如果您的应用在没有数据的情况下无用,请先获取数据。
但是,如果您的应用可能包含数百或数千个这些Video
个实例,而且大多数实例都不会被使用,那么让用户在启动它们时等待是没有意义的。在这种情况下,将初始化推迟到真正需要之前会很有意义。例如,如果您要显示“缩略图墙”显示,则可能需要每个视频和标题的缩略图,但除非用户点击缩略图,否则您可能不需要任何其他内容。
我喜欢一般的方法,使用对象的代码不需要知道或关心对象是否已预先初始化。
答案 1 :(得分:2)
这是lazy loading
。如果不总是需要这些属性,那么值得实现,从api中查询它们将是一种浪费。在中,我创建了一个Video
类,但我不需要这些属性。
当Class属性需要很长时间来获取/加载时,延迟加载是一个好主意。那么在你的情况下,API调用是否昂贵,你的Video
类真的需要吗?关于Video类的更多信息将有助于了解它是否值得实现。延迟加载只是延迟加载会增加代码的复杂性没有充分的理由所以是的,重要的是看看是否需要延迟加载。
在一天结束时,您可以使用应用程序中的Video对象进行您所做的事情。
答案 2 :(得分:1)
Lazy evaluation(或lazy loading或lazy initialization)在后续操作否则需要对后端进行更多查询时,或者当请求是如此时非常有用大块,以大块的方式做这件事,或者当你很有可能不会使用请求的每一部分时......一般来说,这是一种渴望行为的选择(例如range()
in Python 2.x)和laziness(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库......),但这就是它的要点。
答案 3 :(得分:0)
是的,您正在实施延迟评估,并且对于“值得”这个问题的其他答案,它取决于数据的使用模式以及何时让用户等待。另外要记住的一件事是,如果视频数据的拉动可能需要一段时间,但您确信需要数据,则可以在另一个执行线程中提取数据以预取它。
实现您使用的延迟评估类型的一种方法并避免代码中的复杂性是在金字塔库中使用像@reify这样的装饰器。在这个blog entry which contains a link to reify source at the bottom
中查看金字塔库中的@reify装饰器这可能不是你想要实现它的方式,但值得一看“延迟评估”的“pythonic”解决方案。