Python方法查找,静态与实例

Hyp*_*eus 9 python static monkeypatching

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

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

qux = Foo ()
qux.bar ()
Foo.bar (qux)
Run Code Online (Sandbox Code Playgroud)

但是现在我有一个类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
Run Code Online (Sandbox Code Playgroud)

代码工作正常,但让我怀疑的是print Animal.populate (qux)调用静态populate方法的事实(因此返回了一个列表而没有填充糟糕的qux).显然,我的信念Foo ().bar ()只不过Foo.bar (Foo () )是一个简短的手段,这是错误的.

这为我提出了各种问题:

  1. 我打电话后会发生什么Foo ().bar ()
  2. 我打电话后会发生什么Foo.bar (Foo () )
  3. 两者之间是否存在内部差异?
  4. 我错过了一些python的基本概念吗?
  5. 如果你必须编写一个类,其静态populate方法除了在这个类的实例上调用的populate方法之外做了什么,这将是要走的路?

(是的,它必须是同一个名字.)

lvc*_*lvc 2

关于 Foo().bar()、Foo.bar(Foo()) 和 Foo.bar() 之间的区别(作为答案,因为我昨天注册了,还不能发表评论) - 这是因为 Python( <3.0) 的“绑定”和“非绑定”方法的概念 - 它严格要求,除了 @staticmethod 或 @classmethod 之外,方法调用具有与其关联的实例。没有什么比你必须记住的东西更容易解释它的方法了。值得庆幸的是,这在 Python 3 中发生了变化 - “绑定”和“非绑定”方法作为单独事物的概念已经消失,并且 Foo.bar() 对于您的示例来说效果很好。