2017-04-12 4 views
0

Im folgenden Code verstehe ich nicht, warum download_progress_hook funktioniert, ohne Parameter zu übergeben, wenn es aus der maybe_download Methode aufgerufen wird.Warum funktioniert die Funktion ohne Angabe von Parametern?

Die Definition von download_progress_hook besagt, dass drei Parameter übergeben werden müssen: count, blockSize, totalSize. Aber wenn die download_progress_hook von maybe_download aufgerufen wird, gibt es keine Parameter übergeben. Warum versagt es nicht? Hier

ist der vollständige Code:

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

Sie meinen in 'urlretrieve (..., reporthook = download_progress_hook')'? Die Funktion wird ** dort nicht angerufen **. –

Antwort

5

ich alles, aber der Punkt, an dem die Funktion download_progress_hook aus der Funktion aufgerufen wird maybe_download

Das ist, wo Sie schief gelaufen ist. Die Funktion ist wird nicht aufgerufen. Es wird nur referenziert. Es gibt keinen (...) Aufrufausdruck dort.

Python-Funktionen sind erstklassige Objekte, können Sie sie um oder ordnen sie andere Namen passieren kann:

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

Hier spam ist ein weiterer Hinweis auf die Funktionsobjekt. Ich kann dieses Funktionsobjekt auch über diesen anderen Namen aufrufen.

So wird der folgende Ausdruck:

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

nicht Anrufdownload_progress_hook. Es gibt nur dieses Funktionsobjekt an die urlretrieve() Funktion, und es ist , dass Code, die download_progress_hook irgendwo aufrufen (die erforderlichen Argumente übergeben).

Vom URLOpener.retrieve documentation (die letztlich, dass die Haken Griffe):

Wenn reporthook gegeben ist, muss es eine Funktion mit drei numerischen Parameter sein: Ein Stück der Zahl, sind die maximale Größe Brocken lesen und die Gesamtgröße des Downloads (-1 falls unbekannt). Es wird einmal am Anfang und nach jedem Datenpaket vom Netzwerk gelesen.

+0

Vielen Dank Martijn. – kuatroka

Verwandte Themen