【问题标题】:Python method lookup, static vs. instancePython 方法查找,静态与实例
【发布时间】:2011-06-01 20:33:46
【问题描述】:

直到一个小时前,我才确信在 python 中Foo ().bar () 只不过是Foo.bar (Foo () ) 的简写,它将实例作为第一个参数传递。在这个例子中,最后两行(显然)做同样的事情:

class Foo (object):
    def bar (self): print "baz"

qux = Foo ()
qux.bar ()
Foo.bar (qux)

但是现在我有一个 Animal 类,它有一个静态方法 populate(),它返回人类已知的所有动物的列表。此外,Animal 的每个实例都有一个 populate() 方法,该方法用随机值填充实例的属性。

#! /usr/bin/env python
# -*- coding: utf-8 -*-

import random

animals = [ ("Bella", "cow"), ("Spike", "dog"), ("José", "iguana"), ("Tux", "penguin") ]

class Animal (object):
    @staticmethod
    def populate (*args): return map (lambda x: Animal (*x), animals)

    def __init__ (self, name = None, species = None):
        def bar (): self.name, self.species = random.choice (animals)
        self.name = name
        self.species = species
        self.populate = bar

    def __repr__ (self): return "%s of species %s" % (self.name, self.species)

print Animal.populate ()
print Animal ("Pinky", "mouse")
qux = Animal ()
qux.populate ()
print qux

代码运行良好,但让我怀疑的是print Animal.populate (qux) 调用了静态填充方法(因此返回了一个列表并且没有填充可怜的 qux)。所以显然我认为Foo ().bar () 只不过是Foo.bar (Foo () ) 的简写是错误的。

这对我提出了各种问题:

  1. 当我拨打Foo ().bar () 时会发生什么?
  2. 当我拨打Foo.bar (Foo () ) 时会发生什么?
  3. 两者之间是否存在内部差异?
  4. 我是否遗漏了 python 的一些基本概念?
  5. 如果您必须编写一个类,该类的静态填充方法执行的操作除了在该类的实例上调用的填充方法之外,应该采用哪种方式?

(是的,它必须是相同的名称。)

【问题讨论】:

  • 一个更有趣的标题是“Python 方法查找,静态与实例”。使用该术语您可能会得到更多答案,它更具技术性和吸引力。
  • @Santiago 感谢您的意见。我改了标题。
  • () 周围的所有多余空格让我的眼睛受伤
  • De gustibus non est diputandum。我被", ".join(map(lambda x:"%s"%x,zip(*pairs)[1])) 之类的东西伤害了。空白 gusto 与方法查找有何关系?
  • 如果您从不从实例中调用它,我不确定拥有静态方法的意义。您是否将其与来自不同语言的静态方法混淆了?类方法在这里更有意义

标签: python static monkeypatching


【解决方案1】:

关于 Foo().bar()、Foo.bar(Foo()) 和 Foo.bar() 之间的区别(作为答案,因为我昨天注册并且还不能发布 cmets) - 这是因为Python(

【讨论】:

  • 我刚从 python2.7 迁移到 python3.2,现在我体验到的“惊喜”比以前少了。
【解决方案2】:

静态方法和类方法是special descriptors。由于描述符的 __get__() 方法的参数包括类和任何相关实例,它们可以以任何他们喜欢的方式将参数与方法结合起来。

【讨论】:

  • 谢谢。我会阅读链接,很可能会带着更多问题回来。
【解决方案3】:

qnx.populate() 首先在实例qnx 上查找populate。如果不存在,则跟踪 __mro__,直到找到名为 populate 的东西。

Animals.populate(qnx) 正在跳过上述查找的第一步

【讨论】:

  • 非常感谢。我需要一些时间来消化这个。
  • 有没有办法在python中使用MRO进行追踪?
  • @Hyperboreus,该类有一个__mro__ 属性
  • 一件事我不明白。使用class Foo (object): <newline> def bar (*args): print "baz",为什么Foo ().bar ()Foo.bar (Foo () ) 有效,而Foo.bar () 无效?
  • @Hyperboreus,后者是未绑定的方法。如果您遵循使用显式自我的通常约定,这一点会更加明显。 def bar(self, *args)。前 2 个将实例作为 self 传递。第一个是因为它是一个绑定方法,第二个是因为你显式地传递了一个实例。写def bar(*args) 不会让你不传入一个实例而侥幸,它只是把它伪装成args 的第一个元素
猜你喜欢
  • 2012-11-12
  • 1970-01-01
  • 2015-06-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-30
相关资源
最近更新 更多