2017-04-12 84 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

相關問題