2011-06-01 60 views
9

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

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

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

但现在我有了一个静态方法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. 如果您必须编写一个类,其静态填充方法除了通过此类的一个实例调用的填充方法之外还有其他内容,那么这将是什么方法?

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

+0

更有趣的标题是“Python方法查找,静态与实例”。您可以使用该术语获得更多答案,但技术性更强,更具吸引力。 – slezica 2011-06-01 20:37:39

+0

@Santiago感谢您的意见。我改变了标题。 – Hyperboreus 2011-06-01 20:43:00

+2

'()'周围的所有额外空间使我的眼睛受伤 – 2011-06-01 21:23:37

回答

2

第一步于foo()之间的差值。如因为我的答案这是因为Python(< 3.0)的'绑定'和'非绑定'方法的概念 - 它严格要求,除了@staticmethod或@classmethod,方法调用有与他们关联的实例。没有什么更简单的方法来解释它,而不仅仅是你必须记住的东西。 谢天谢地,这已经在Python 3中发生了变化 - 作为单独的东西的'bound'和'unbound'方法的概念已经消失,并且Foo.bar()对您的示例工作得很好。

+0

太好了。这帮了很多。 – Hyperboreus 2011-06-01 23:43:39

+0

我刚刚从python2.7移动到python3.2,现在我的体验比以前少了“惊喜”。 – Hyperboreus 2011-06-02 19:53:05

2

静态方法和类的方法special descriptors。由于描述符的方法参数包括类和任何相关的实例,因此它们可以以任何他们喜欢的方式与方法的参数一起使用。

+0

谢谢。我会阅读链接,最有可能回来更多的问题。 – Hyperboreus 2011-06-01 20:43:41

0

qnx.populate()首先看实例qnxpopulate。如果不存在__mro__,那么直到找到名为populate的东西。

Animals.populate(qnx)被巴(),Foo.bar(美孚())和Foo.bar()(跳过在上述查找

+0

非常感谢。我需要一些时间来消化这个。 – Hyperboreus 2011-06-01 21:37:45

+0

有没有办法在python中跟踪MRO? – Hyperboreus 2011-06-01 21:53:48

+0

@Hyperboreus,该类有'__mro__'属性 – 2011-06-01 21:56:08