[英]What happens to `for i in range()` when iterator is overwritten in nested while loop?
[英]What happens to the variable in this case when it is overwritten with self?
我正在使用Python下载URL,并且需要检测404,因此经过一番搜索,我想到了:
import urllib
class MyUrlOpener(urllib.FancyURLopener):
def retrieve(self, url, filename=None, reporthook=None, data=None):
self.file_was_found = True
val = urllib.FancyURLopener.retrieve(self, url, filename, reporthook, data)
return val
def http_error_404(url, fp, errcode, errmsg, headers, data):
url.file_was_found = False
def download_file(url, saveas):
urlaccess = MyUrlOpener()
localFile, headers = urlaccess.retrieve(url, saveas)
return urlaccess.file_was_found
我的问题是,如果您查看FancyURLopener的源代码(Python 2.7),则会看到:
def http_error(self, url, fp, errcode, errmsg, headers, data=None):
"""Handle http errors.
Derived class can override this, or provide specific handlers
named http_error_DDD where DDD is the 3-digit error code."""
# First check if there's a specific handler for this error
name = 'http_error_%d' % errcode
if hasattr(self, name):
method = getattr(self, name)
if data is None:
result = method(url, fp, errcode, errmsg, headers)
else:
result = method(url, fp, errcode, errmsg, headers, data)
if result: return result
return self.http_error_default(url, fp, errcode, errmsg, headers)
这将url
作为第一个参数而不是self
传递。 我认为函数的第一个参数始终是对类实例的引用(按照惯例),我的代码对此进行了确认。 那么url
值会怎样?
更新:结果data==None
所以它正在调用第一个签名。 这挫败了我手动添加self参数的尝试。 在我将http_error_404
签名中的data
添加=None
默认值后,一切就很好了(因为它使用了默认值)。
固定 / 正确的签名是def http_error_404(self, url, fp, errcode, errmsg, headers, data=None):
在Python中,任何类实例的方法都由Python解释器self
传递,并且所有其他参数自动下移一个位置。
换句话说,Python解释器将重写:
urlaccess.retrieve(url, saveas)
变成这样的东西:
urlaccess.retrieve(urlaccess, url, saveas)
因此,您不必自己做。 但是,由于
显式胜于隐式
您为Python对象声明的任何实例方法都必须明确指定它们将对象的实例作为其第一个参数, 即使Python无需程序员的任何操作也可以传递该参数。
第一个参数没有被称为self
......这仅仅是一个约定。
因此,要真正回答您的问题(如mluebke所做的那样),您需要指定self
参数。
def http_error_404(url, fp, errcode, errmsg, headers, data):
url.file_was_found = False
# Python is treating `url` as `self`
# Therefore the URL is being saved in `fp`, `fp` in `errcode`, etc.
要解决此问题,请添加第一个参数以选择实例。
def http_error_404(self, url, fp, errcode, errmsg, headers, data):
self.file_was_found = False
# Now everything should work
self在方法定义中明确列出,但在调用方法时隐式传递。 更改函数,使其看起来像这样,所有变量将重新开始排列。
def http_error_404(self, url, fp, errcode, errmsg, headers, data):
self.file_was_found = False
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.