2009-05-04 14 views
5

Ho letto il tutorial di tempesta ORM a https://storm.canonical.com/Tutorial, e mi sono imbattuto il seguente pezzo di codice:quale funzione python è illustrata in questo codice?


store.find(Person, Person.name == u"Mary Margaret").set(name=u"Mary Maggie") 

non sono sicuro che il secondo argomento del trovare metodo sarà valutata a Vero/Falso. Penso che sarà interpretato come un lambda. Se questo è vero, come posso ottenere lo stesso effetto nelle mie funzioni?

risposta

0

dal momento che sono un programmatore Java ... Sto indovinando ... l'operatore sta sovraccaricando? Person.name == è un operatore sovraccaricato che invece fare il confronto ... produce una query SQL

mia 0.02 $

+0

Java e l'overloading dell'operatore ... non credo che si avvererà mai. Dall'altra parte, forse hai ragione. – Geo

+10

Dispari .... Accettare una risposta di "indovinare" quando un'altra risposta si basa sul codice sorgente effettivo in Storm. –

+0

scusa, ma la mia ipotesi era "abbastanza veloce" :-) PS hai ragione, è molto strano! – dfa

1

Non sembra come un pitone lambda per me. Non ho letto il codice per Storm ma Miles ha probabilmente ragione nel fatto che utilizza uno schema di valutazione pigro.

Per ulteriori informazioni sulle funzioni lambda di python, leggere l'eccellente chapter di Dive Into Python.

+0

Ho sempre pensato che le funzioni lambda dovessero essere precedute dalla parola chiave lambda, quindi non poteva essere così, giusto? – Geo

22

Person.name ha un metodo sovraccarico __eq__ che non restituisce un valore booleano ma un oggetto che memorizza entrambi i lati dell'espressione; quell'oggetto può essere esaminato dal metodo find() per ottenere l'attributo e il valore che utilizzerà per il filtraggio. Descriverei questo come un tipo di modello di valutazione pigro.

In Storm, è implementato con Comparable object.

9

Person.name è un esempio di una certa digitare con un metodo personalizzato __eq__. Mentre __eq__ normalmente restituisce un valore booleano (ish), può effettivamente restituire tutto ciò che si desidera, incluso un lambda. Vedi Python special method names per ulteriori informazioni su questo e sui metodi correlati.

Probabilmente la/parte fuorviante più confuso di questo (soprattutto se si è abituati ad altri linguaggi OO come Java) è che Person.name e person.name (dove person è un'istanza di Person) non avere alcun rapporto con l'un l'altro. Per esempio:

class Person(object): 
    name = "name of class" 
    def __init__(self): 
    self.name = "name of instance" 

person = Person() 
print Person.name 
print person.name 

Questo stamperà:

name of class 
name of instance 

notare che la proprietà di classe è solo trova nel corpo della classe, mentre la proprietà istanza viene impostata nel metodo __init__.

Nel tuo caso, quando si imposta Person.name per l'oggetto con il __eq__ metodo personalizzato che restituisce un lambda, qualcosa di simile:

class LambdaThingy(object): 
    def __init__(self, attrname): 
    self.__attrname = attrname 

    def __eq__(self, other): 
    return lambda x: getattr(x, self.__attrname) == other 

class Person(object): 
    name = LambdaThingy('name') 

    def __init__(self, name): 
    self.name = name 

equals_fred = Person.name == "Fred" 
equals_barney = Person.name == "Barney" 

fred = Person("Fred") 

print equals_fred(fred) 
print equals_barney(fred) 

Questo stampa:

True 
False 

questo è certamente sfiorando il limite di essere "troppo intelligente", quindi sarei molto cauto nell'usare questo nel codice di produzione. Un lambda esplicito sarebbe probabilmente molto più chiaro per i futuri manutentori, anche se è un po 'più prolisso.

+0

+1 per la grande spiegazione della parte "troppo intelligente"! – lothar

Problemi correlati