【问题标题】:what python feature is illustrated in this code?此代码中说明了哪些 python 功能?
【发布时间】:2009-05-04 20:21:03
【问题描述】:

我在https://storm.canonical.com/Tutorial 阅读了 Storm ORM 的教程,我偶然发现了以下代码:


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

我不确定 find 方法的第二个参数是否会被评估为 True/False。我认为它将被解释为 lambda。如果是这样,我怎样才能在我的函数中实现相同的效果?

【问题讨论】:

    标签: python language-features


    【解决方案1】:

    Person.name 有一个重载的__eq__ 方法,它返回的不是布尔值,而是一个存储表达式两边的对象;可以通过find() 方法检查该对象,以获得它将用于过滤的属性和值。我会将其描述为一种惰性求值模式。

    在 Storm 中,它是通过 Comparable object 实现的。

    【讨论】:

      【解决方案2】:

      Person.name 是具有自定义__eq__ 方法的某种类型的实例。虽然__eq__ 通常返回一个布尔值(ish),但它实际上可以返回任何你想要的,包括一个 lambda。有关此方法和相关方法的更多信息,请参阅Python special method names

      可能最令人困惑/误导的部分(尤其是如果您习惯于其他 OO 语言,例如 Java)是 Person.nameperson.name(其中 personPerson 的一个实例)不要'彼此之间不必有任何关系。例如:

      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__方法中设置的。

      在您的情况下,您可以使用返回 lambda 的自定义 __eq__ 方法将 Person.name 设置为对象,如下所示:

      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
      

      这肯定是在避开“太聪明”的边缘,所以我会非常谨慎地在生产代码中使用它。对于未来的维护者来说,显式的 lambda 可能会更清晰,即使它有点冗长。

      【讨论】:

        【解决方案3】:

        神奇之处在于 Person.name 属性,它会导致类型重载 __eq__ (&c) 以返回非布尔值。 Storm 的资源在线供您浏览(并谨慎模仿;-)http://bazaar.launchpad.net/~storm/storm/trunk/files/head%3A/storm/ - 正如您将看到的,它们并没有阐明“黑魔法”;-)

        【讨论】:

          【解决方案4】:

          在我看来,它不像 python lambda。我没有阅读 Storm 的代码,但 Miles 可能是对的,因为它使用了惰性求值模式。

          要了解有关 python lambda 函数的更多信息,请阅读优秀的 chapterDive Into Python

          【讨论】:

          • 我一直认为 lambda 函数必须以 lambda 关键字为前缀,所以不可能这样吧?
          【解决方案5】:

          因为我是一名 Java 程序员...我猜... 是运算符重载吗? Person.name == 是一个重载的运算符,而是进行比较...它产生一个 SQL 查询

          我的 0.02 美元

          【讨论】:

          • Java 和运算符重载......不要认为它会成为现实。另一方面,也许你是对的。
          • Odd.... 当另一个答案基于 Storm 中的实际源代码时,接受“猜测”答案。
          • 抱歉,但我的猜测是“足够快” :-) PS 你是对的,这很奇怪!
          • 公平地说,猜测的答案正确的,即使它不是最清楚的。
          猜你喜欢
          • 1970-01-01
          • 2018-01-14
          • 2012-08-08
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-05-02
          • 2018-07-16
          • 1970-01-01
          相关资源
          最近更新 更多