哪个更有效:将对象用作 class 属性?或者在需要时重新初始化?
Which is more efficient: to use object as class attribute? Or to reinitialize when needed?
我正在用 Scrapy 构建一个蜘蛛/抓取器,我想知道哪个更有效:将一个 API 包装器对象初始化一次作为 class 属性?或者重新初始化每个 URL 请求?我想知道整体效率和内存(泄漏)的情况,因为这将是一个相当大的项目(数百万个请求)。
案例 1:
# init API wrapper ONCE as class attribute
class ScrapySpider():
api = SomeAPIWrapper()
urls = [
'https://website.com',
# ... +1mil URLs
]
def request(self):
for url in urls:
yield Request(url)
def parse(self, response):
yield self.api.get_meta(response.url)
案例二:
# init new API wrapper on EACH request
class ScrapySpider():
urls = [
'https://website.com',
# ... +1mil URLs
]
def request(self):
for url in urls:
yield Request(url)
def parse(self, response):
api = SomeAPIWrapper()
yield api.get_meta(response.url)
在示例代码中,使用 class 属性(案例 1)应该更有效。
这个问题没有通用的、放之四海而皆准的答案——这取决于对象实例化的成本、在最佳/平均/最坏情况下最终实例化它的频率,以及您的使用 class 属性(而不是实例属性)的示例,在主机 class.
的所有实例之间共享此对象是否安全
请注意,还有两个替代项:
1/ 在初始化程序中创建的每个实例属性:
class ScrapySpider():
def __init__(self, *args, **kw):
super().__init__(*args, **kw)
self.api = SomeAPIWrapper()
这避免了使用 class 属性可能遇到的并发访问问题,并且
2/个缓存属性
class ScrapySpider():
@property
def api(self):
if not hasattr(self, "_cached_api"):
self._cached_api = ApiWrapper()
return self._cached_api
这也会阻止在需要之前创建 ApiWrapper 实例(如果创建它的成本很高并且并不总是需要它,则可能会有用)但会增加属性访问的少量开销。
我正在用 Scrapy 构建一个蜘蛛/抓取器,我想知道哪个更有效:将一个 API 包装器对象初始化一次作为 class 属性?或者重新初始化每个 URL 请求?我想知道整体效率和内存(泄漏)的情况,因为这将是一个相当大的项目(数百万个请求)。
案例 1:
# init API wrapper ONCE as class attribute
class ScrapySpider():
api = SomeAPIWrapper()
urls = [
'https://website.com',
# ... +1mil URLs
]
def request(self):
for url in urls:
yield Request(url)
def parse(self, response):
yield self.api.get_meta(response.url)
案例二:
# init new API wrapper on EACH request
class ScrapySpider():
urls = [
'https://website.com',
# ... +1mil URLs
]
def request(self):
for url in urls:
yield Request(url)
def parse(self, response):
api = SomeAPIWrapper()
yield api.get_meta(response.url)
在示例代码中,使用 class 属性(案例 1)应该更有效。
这个问题没有通用的、放之四海而皆准的答案——这取决于对象实例化的成本、在最佳/平均/最坏情况下最终实例化它的频率,以及您的使用 class 属性(而不是实例属性)的示例,在主机 class.
的所有实例之间共享此对象是否安全请注意,还有两个替代项:
1/ 在初始化程序中创建的每个实例属性:
class ScrapySpider():
def __init__(self, *args, **kw):
super().__init__(*args, **kw)
self.api = SomeAPIWrapper()
这避免了使用 class 属性可能遇到的并发访问问题,并且
2/个缓存属性
class ScrapySpider():
@property
def api(self):
if not hasattr(self, "_cached_api"):
self._cached_api = ApiWrapper()
return self._cached_api
这也会阻止在需要之前创建 ApiWrapper 实例(如果创建它的成本很高并且并不总是需要它,则可能会有用)但会增加属性访问的少量开销。