Какая особенность 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.

Другие вопросы по тегам