2010-10-27 21 views
5

Ho il seguente codice che sto cercando di capire:__call__ comprensione e list.sort (chiave)

>>> class DistanceFrom(object): 
     def __init__(self, origin): 
      self.origin = origin 
     def __call__(self, x): 
      return abs(x - self.origin) 

>>> nums = [1, 37, 42, 101, 13, 9, -20] 
>>> nums.sort(key=DistanceFrom(10)) 
>>> nums 
[9, 13, 1, 37, -20, 42, 101] 

qualcuno può spiegare come funziona? Per quanto ho capito, __call__ è ciò che viene chiamato quando si chiama object() - chiamando l'oggetto come una funzione.

Quello che non capisco è come nums.sort(key=DistanceFrom(10)). Come funziona? Qualcuno può spiegare questa linea?

Grazie!

risposta

7

Qui ho definito una funzione DistanceFrom() che può essere utilizzato in modo simile alla classe, ma potrebbe essere più facile da seguire

>>> def DistanceFrom(origin): 
...  def f(x): 
...   retval = abs(x - origin) 
...   print "f(%s) = %s"%(x, retval) 
...   return retval 
...  return f 
... 
>>> nums = [1, 37, 42, 101, 13, 9, -20] 
>>> nums.sort(key=DistanceFrom(10)) 
f(1) = 9 
f(37) = 27 
f(42) = 32 
f(101) = 91 
f(13) = 3 
f(9) = 1 
f(-20) = 30 
>>> nums 
[9, 13, 1, 37, -20, 42, 101] 

così si vede che l'oggetto restituito da DistanceFrom è chiamato una volta per ogni elemento di nums e poi nums viene restituito risolto in accordo con i valori restituiti

+0

Grazie! Questo è perfetto. – user225312

+0

@Alfred, sei il benvenuto –

4

Ordina l'elenco nums utilizzando un oggetto funzione keyDistanceFrom(10). Deve essere chiamabile perché key deve essere richiamabile. L'output risultante è ordinato in base alla loro "lontananza" da 10, cioè 9 è il valore più vicino a 10, 101 è il più lontano.

Dopo che l'oggetto viene inizializzato e passato come parametro key al metodo sort, ad ogni iterazione sarà chiamato con il valore corrente (che è quello x è) e il valore restituito sarebbero stati utilizzati per determinare la posizione x s' in la lista risultante.

+0

Come viene eseguito? Voglio dire, DistanceFrom (10) imposta self.origin = 10. Dopo quello? – user225312

+0

@Alfred: vedi la mia modifica – SilentGhost

+0

"__ init __" è un costruttore che viene chiamato durante la creazione del tasto Oggetto – OlimilOops

8

__call__ in python consente a una classe di essere eseguita come se fosse una funzione. Si può provare questo manualmente:

>>> dis = DistanceFrom(10) 
>>> print dis(10), dis(5), dis(0) 
0 5 10 
>>> 

Che fa è chiamare tale funzione per ogni elemento nella vostra lista e utilizza il valore restituito come chiave di ordinamento. In questo esempio otterrai una lista con gli elementi più vicini a 10 prima e l'altro più lontano verso la fine.

+0

Aah. Questo è buono. – user225312

+0

@user: la tua risposta è stata perfetta, ma ho accettato la risposta di gnibbler dato che sarebbe vantaggioso per i principianti nel caso in cui lo cercassero. – user225312

1

Quando si chiama qualcosa significa che ci si aspetta che restituisca un valore. Quando crei una classe con il metodo __call__ definito, stai dettando che un'istanza di quella classe può comportarsi come una funzione.

Ai fini di questa domanda, questa:

class DistanceFrom(object): 
     def __init__(self, origin): 
      self.origin = origin 
     def __call__(self, x): 
      return abs(x - self.origin) 

è funzionalmente equivalente a:

def distance_from(origin, other): 
    return abs(other - origin) 

quanto riguarda l'argomento key per ordinare, qui è la tua spiegazione direttamente dalla documentazione di Python:

chiave specifica una funzione di un argomento che viene utilizzato per estrarre una chiave di confronto da ciascun elemento dell'elenco: key=str.lower.Il valore predefinito è Nessuno (confrontare gli elementi direttamente)

1

I documenti Python sono abbastanza buoni ogni volta che trovo che non capisco i fondamenti. Ho individuato questi con Google.

The key parameter è una funzione che sort chiamerà sugli elementi della lista. Ho trovato questo documento googling sort site:http://docs.python.org/ e quindi cercando key=.

__call__ è una funzione che è possibile aggiungere a un oggetto per rendere quell'oggetto richiamabile come se fosse una funzione. Ho trovato questo documento googling __call__ site:http://docs.python.org/ e quindi seguendo il link al documento per __call__.

+0

Capisco cosa sono, la mia domanda era specifica per questo esempio. – user225312

Problemi correlati