2017-04-12 80 views
0

在下面的代码中,我不明白为什么download_progress_hookmaybe_download方法中调用它时没有传递参数。为什么函数在没有指定参数的情况下正常工作?

download_progress_hook的定义指出有三个参数需要传递:count, blockSize, totalSize。 但是,从maybe_download调用download_progress_hook时,没有参数传递。为什么它不会失败?

下面是完整的代码:

url = 'http://commondatastorage.googleapis.com/books1000/' 
last_percent_reported = None 
data_root = '.' # Change me to store data elsewhere 

def download_progress_hook(count, blockSize, totalSize): 
    """A hook to report the progress of a download. This is mostly intended for users with 
    slow internet connections. Reports every 5% change in download progress. 
    """ 
    global last_percent_reported 
    percent = int(count * blockSize * 100/totalSize) 

    if last_percent_reported != percent: 
    if percent % 5 == 0: 
     sys.stdout.write("%s%%" % percent) 
     sys.stdout.flush() 
    else: 
     sys.stdout.write(".") 
     sys.stdout.flush() 

    last_percent_reported = percent 

def maybe_download(filename, expected_bytes, force=False): 
    """Download a file if not present, and make sure it's the right size.""" 
    dest_filename = os.path.join(data_root, filename) 
    if force or not os.path.exists(dest_filename): 
    print('Attempting to download:', filename) 
    filename, _ = urlretrieve(url + filename, dest_filename, reporthook=download_progress_hook) 
    print('\nDownload Complete!') 
    statinfo = os.stat(dest_filename) 
    if statinfo.st_size == expected_bytes: 
    print('Found and verified', dest_filename) 
    else: 
    raise Exception(
     'Failed to verify ' + dest_filename + '. Can you get to it with a browser?') 
    return dest_filename 

train_filename = maybe_download('notMNIST_large.tar.gz', 247336696) 
test_filename = maybe_download('notMNIST_small.tar.gz', 8458043) 
+2

你的意思是'urlretrieve(...,reporthook = download_progress_hook')'? **没有被调用**。 –

回答

5

我得到的一切,但在功能download_progress_hook会从功能maybe_download

这就是你出了错内调用点。功能是不叫。它只被引用。那里没有(...)调用表达式。

Python的职能是一流的对象,你可以通过他们周围或将其分配给其他的名字:

>>> def foo(bar): 
...  return bar + 1 
... 
>>> foo 
<function foo at 0x100e20410> 
>>> spam = foo 
>>> spam 
<function foo at 0x100e20410> 
>>> spam(5) 
6 

这里spam是另一个参考函数对象foo。我也可以通过那个其他的名字来调用这个函数对象。

所以下面的表达式:

urlretrieve(
    url + filename, dest_filename, 
    reporthook=download_progress_hook) 

呼叫download_progress_hook。它只是将该函数对象赋予urlretrieve()函数,并且它是,其代码将在某处调用download_progress_hook(传递所需参数)。

URLOpener.retrieve documentation(其最终处理该钩):

如果reporthook给出,它必须是接受三个数值参数的函数:一个组块数,最大尺寸块被读入和下载的总大小(如果未知,则为-1)。它将在开始时以及从网络读取每个数据块后调用一次。

+0

非常感谢Martijn。 – kuatroka

相关问题