直到一小时前,我确信在python Foo ().bar ()
中只不过是Foo.bar (Foo () )
的简写,它将实例作为第一个参数传递。在这个例子中,最后两行(显然)做了同样的事情:
class Foo (object):
def bar (self): print "baz"
qux = Foo ()
qux.bar ()
Foo.bar (qux)
但是现在我有一个Animal类,它有一个静态方法populate(),它返回man已知的所有动物的列表。此外,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 () )
的简称,这是错误的。
这为我提出了各种问题:
Foo ().bar ()
时会发生什么?Foo.bar (Foo () )
时会发生什么?(是的,它必须是同一个名字。)
答案 0 :(得分:2)
静态方法和类方法是special descriptors。由于描述符的__get__()
方法的参数包括类和任何相关实例,因此他们可以以任何他们喜欢的方式使用方法的参数。
答案 1 :(得分:2)
关于Foo()。bar(),Foo.bar(Foo())和Foo.bar()之间的区别(作为答案,因为我昨天注册了,还不能发表评论) - 这是因为Python(< 3.0)的'bound'和'unbound'方法的概念 - 它严格要求除了@staticmethod或@classmethod之外,方法调用都有一个与之关联的实例。解释它的方法并不比你必须要记住的东西更简单。 值得庆幸的是,这在Python 3中已经发生了变化 - “绑定”和“未绑定”方法的概念已经消失了,而且Foo.bar()在您的示例中运行良好。
答案 2 :(得分:0)
qnx.populate()
首先查看qnx
的实例populate
。如果不存在,则会跟踪__mro__
,直到找到名为populate
的内容。
Animals.populate(qnx)
正在跳过上述查找的第一步