Какая особенность Python проиллюстрирована в этом коде?
Я прочитал учебник по Storm ORM по адресу https://storm.canonical.com/Tutorial и наткнулся на следующий фрагмент кода:
store.find(Person, Person.name == u"Mary Margaret").set(name=u"Mary Maggie")
Я не уверен, что второй аргумент метода find будет оценен как True / False. Я думаю, что это будет интерпретироваться как лямбда. Если это правда, как я могу добиться того же эффекта в моих функциях?
5 ответов
Так как я программист на Java... я думаю... это перегрузка операторов? Person.name == перегружен оператор, который вместо этого выполняет сравнение... он производит запрос SQL
мой 0,02$
Person.name
перегружен __eq__
метод, который возвращает не логическое значение, а объект, который хранит обе стороны выражения; этот объект может быть исследован find()
метод для получения атрибута и значения, которые он будет использовать для фильтрации. Я бы описал это как тип ленивого шаблона оценки.
В Storm это реализовано с Comparable
объект.
Person.name
это экземпляр какого-то типа с обычаем __eq__
метод. В то время как __eq__
обычно возвращает логическое значение (ish), оно может возвращать все, что вы хотите, включая лямбду. Посмотрите имена специальных методов Python для более подробной информации об этом и связанных методах.
Вероятно, наиболее запутывающей / вводящей в заблуждение частью этого (особенно если вы привыкли к другим языкам программирования, таким как Java) является то, что Person.name
а также person.name
(где person
это пример Person
) не должны иметь никакого отношения друг к другу. Например:
class Person(object):
name = "name of class"
def __init__(self):
self.name = "name of instance"
person = Person()
print Person.name
print person.name
Это напечатает:
name of class name of instance
Обратите внимание, что свойство класса просто устанавливается в теле класса, а свойство экземпляра устанавливается в __init__
метод.
В вашем случае вы бы установили Person.name
к объекту с обычаем __eq__
метод, который возвращает лямбду, что-то вроде этого:
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)
Это печатает:
True
False
Это, безусловно, обходит край "слишком умного", поэтому я буду очень осторожен при использовании этого в производственном коде. Явная лямбда, вероятно, будет намного понятнее будущим сопровождающим, даже если она будет более многословной.
Магия находится в свойстве Person.name, что приводит к перегрузке типа __eq__
(&c) вернуть не-bools. Вы можете просмотреть исходные тексты Storm (и ВНИМАТЕЛЬНО подражать;-) на http://bazaar.launchpad.net/~storm/storm/trunk/files/head%3A/storm/ - как вы увидите, они не ходи на "черную магию";-)
Это не похоже на лямбду питона для меня. Я не читал код для Storm, но Майлз, вероятно, прав в том, что он использует ленивую схему оценки.
Чтобы узнать больше о лямбда-функциях Python, прочитайте превосходную главу Dive Into Python.