繁体   English   中英

在这种情况下,变量被自身覆盖时会发生什么?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM