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 21 586×
Přečteno 12 848×
Přečteno 11 027×
Přečteno 10 444×
Přečteno 10 221×