SQLAlchemy je nekonečný zdroj inspirace. Několikrát jsem si řekl: Jak to asi dělají. A protože je to Python, tak jsem za okamžik věděl. Buď jsem na to kápnul sám (Wu-Shiho kleště), nebo jsem se podíval do kódu. O co se s vámi podělím dnes?
Nadefinujete si tabulku, třeba takhle:
person = Table("person", metadata, Column("id", Integer()), Column("name", Unicode()), Column("address", Unicode()), Column("sex", Integer()), Column("regtm", DATETIME()), )
A pak sestavíte dotaz:
q = person.select().where( person.c.name=="John Smith" and person.c.regt>datetime.datetime(2012, 1, 1) )
Mě se moc líbila konstrukce té where clause, tak jsem si řekl, jak to asi dělají? Je to samozřejmně banální. V Pythonu lze pro objekt nadefinovat význam operátorů. SQLAlchemy pro objekt Column definuje porovnání, and, a další. Výsledkem těchto operátorů je pak objekt, který dokáže vygenerovat kus SQL.
Ukážeme si jednoduchý příklad, na stejném principu, ale pro symbolickou aritmetiku, a s těmi nejjednoduššími operacemi. Začneme výrazem, nad kterým nadefinujeme sčítání, odčítání, násobení a dělení.
class Expression(object): def __add__(self, rt): return Plus(self, rt) def __sub__(self, rt): return Minus(self, rt) def __mul__(self, rt): return Multiply(self, rt) def __div__(self, rt): return Divide(self, rt) class BinaryOperation(Expression): def __init__(self, lt, rt): self.lt = lt self.rt = rt def __str__(self): return "(%s %s %s)" % (self.lt, self.__class__.OPERATOR, self.rt) class Plus(BinaryOperation): OPERATOR = "+" class Minus(BinaryOperation): OPERATOR = "-" class Multiply(BinaryOperation): OPERATOR = "*" class Divide(BinaryOperation): OPERATOR = "/"
Nechci vysvětlovat, co dělá která funkce. To si najdete v dokumentaci, a vyzkoušíte. Teď přidáme symboly:
class Primary(Expression): pass class Symbol(Primary): def __init__(self, name): self.name = name def __str__(self): return self.name
No, a teď už nám bude fungovat Symbol(„a“)*Symbol(„b“). Zkuste si tohle:
print Symbol("a")+Symbol("b")*Symbol("e")-Symbol("c")/Symbol("d") print (Symbol("a")+Symbol("b"))*Symbol("e")-Symbol("c")/Symbol("d") print (Symbol("a")+Symbol("b")*Symbol("e")-Symbol("c"))/Symbol("d")
Ano, ano. Python předpokládá, že plus je plus a krát je krát, takže fungují priority, a fungují také závorky. Chcete si naprogramovat vlastní systém na symbolickou matematiku? Jo. Nedělejte to. Použijte http://scipy.org/. Nebo http://sympy.org/.
Já osobně si myslím, že na ukázku to stačí, ale jestli to téma chcete rozebrat víc, napište komentář. Co tak? Proč funguje Symbol(“a”)*3, ale nefunguje 3*Symbol(“a”), jak udělat ohodnocení, nic dalšího mě teď nenapadá.
[1] podla mna ide len o to, ako to bude pouzite. Keby v nejakom prog. jazyku islo nadefinovat "+" len ako syntactic sugar pre obj1.plus(obj2) a ludia by vedeli davat vhodne pomenovania metod, tak by "predefinovanie" plus malo vzdy zmysel. Inak skor nie, lebo to potom plynie casto len z lenivosti a nastava nieco ako
if ( new Person("Karel", 195) > new Person("Pepa", 170) ) ...
Tam nie je na prvy pohlad jasne, co sa porovnava a aky to da vysledok, co by mohol napravit vhodny nazov volanej metody (a teda nepouzitie operatoru).
Inde podla mna nie je problem - a programatorov to urcite nepletie, ak su operacie predefinovane na stringoch (concat) alebo prirodzene zadefinovane na bignum triede.
Určitě se to nesmí přehánět, a nepoužívat tam, kde ta sémantika nefunguje. Ale třeba když dělám v sympy integrál nějakýho složitějšího výrazu, tak jsem za ty symboly rád. Na druhou stranu v tom SQL Alchemy používám už jen porovnávání, a i pro logické operátory použiju raději funkce and_, or_, not_ (a stejně tak in_ ).
Jmenuju se Petr Blahoš. Programuju něco přes 20 let. Tady se snažím psát hlavně o Pythonu, webovém frameworku Pyramid, a občas i o něčem úplně jiném.
Přečteno 19 046×
Přečteno 11 772×
Přečteno 9 166×
Přečteno 8 669×
Přečteno 8 467×