Python 方法查找,静态与实例

发布于 2024-11-11 18:17:20 字数 1487 浏览 8 评论 0原文

直到大约一小时前,我确信在 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) 调用静态 populate 方法(因此返回一个列表并且没有填充可怜的 qux)。显然,我认为 Foo ().bar () 只是 Foo.bar (Foo () ) 的简写是错误的。

这给我带来了各种问题:

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

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

Until like one hour ago, I was convinced that in python Foo ().bar () was nothing more than a short hand for Foo.bar (Foo () ) which passes the instance as first parameter. In this example the last two lines do (apparently) the same thing:

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

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

But now I have a class Animal that has a static method populate() that returns a list of all animals known to man. Also each instance of Animal has a method populate() that fills the properties of the instance with random values.

#! /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

The code works fine, but what made me suspicious was the fact that print Animal.populate (qux) called the static populate method (and hence returned a list and did not populate poor qux). So apparently my conviction that Foo ().bar () was nothing more than a short hand for Foo.bar (Foo () ) is wrong.

This raises various questions for me:

  1. What happens when I call Foo ().bar ()?
  2. What happens when I call Foo.bar (Foo () )?
  3. Is there an internal difference between the both?
  4. Am I missing some fundamental concept of python?
  5. If you had to write a class whose static populate method does something else than the populate method invoked over an instance of this class, which would be the way to go?

(Yes it must be the same name.)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

本王不退位尔等都是臣 2024-11-18 18:17:20

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

On the difference between Foo().bar(), Foo.bar(Foo()) and Foo.bar() (as an answer because I signed up yesterday and can't post comments yet) - this is because of Python(<3.0)'s concept of 'bound' and 'unbound' methods - it strictly requires that, except with @staticmethod or @classmethod, method calls have an instance associated with them. There's not really any easier way to explain it than just something you have to remember.
Thankfully, this has changed in Python 3 - the concept of 'bound' and 'unbound' methods as separate things has gone, and Foo.bar() works just fine for your example.

记忆で 2024-11-18 18:17:20

静态方法和类方法是特殊描述符。由于描述符的 __get__() 方法的参数包括类和任何相关实例,因此他们可以以任何他们喜欢的方式修改方法的参数。

Static methods and class methods are special descriptors. Since the descriptor's __get__() method's arguments include both the class and any relevant instance, they can screw with the arguments to the method in any way they like.

梅窗月明清似水 2024-11-18 18:17:20

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

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

qnx.populate() first looks on the instance qnx for populate. If that is not there the __mro__ is followed until something called populate is found.

Animals.populate(qnx) is skipping the first step in the above lookup

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文