【问题标题】:Python simple class understandingPython简单类理解
【发布时间】:2016-02-13 07:31:45
【问题描述】:

我在练习基本的 Python 脚本时从网站上找到了以下代码。从下面的代码中,我能够理解类和实例以及第一个打印语句。

但我不明白第二个和第三个打印语句背后使用的概念。如何将实例(在下面的代码polly 中)作为参数传递给类的方法? python中是否有任何选项可以让我们这样传递?

class Pet(object):

    def __init__(self, name, species):
        self.name = name
        self.species = species

    def getName(self):
        return self.name

    def getSpecies(self):
        return self.species

    def __str__(self):
        return "%s is a %s" % (self.name, self.species)

polly = Pet("Polly", "Parrot")

print "Polly is a %s" % polly.getSpecies()
Polly is a Parrot

print "Polly is a %s" % Pet.getSpecies(polly)
Polly is a Parrot

print "Polly is a %s" % Pet.getSpecies()
Traceback (most recent call last):
  File "", line 1, in
  TypeError: unbound method getSpecies() must be called with Pet instance as first argument (got nothing instead)

【问题讨论】:

  • 很短:看看self。在第一种情况下,self 作为第一个参数隐式发送到getSpecies,因为在实例上调用了getSpeciesself 在这种情况下是Pet 的一个实例,即polly。在第二种情况下,self 显式作为getSpecies 的参数给出,因为该方法不是在实例上调用,而是在类上调用。而self 参数恰好是polly
  • 有问题的代码是 Python 2 特定的,Python 3 中第三条语句的行为略有改变;不要求使用 Pet 实例专门调用未绑定的方法。

标签: python pass-by-reference python-2.x


【解决方案1】:

其实instance.instance_method()内部会变成TheClass.instance_method(instance)self指的是实例本身。所以第一个和第二个版本是相等的。

一个简单的例子:

def getSpeciesGlobal(some_object):  # a normal function
    return some_object.species

polly = Pet("Polly", "Parrot")
polly.species   # "Parrot"
getSpeciesGlobal(polly)   # "Parrot"
# if we assign this function to the class.
Pet.getSpeciesGlobal = getSpeciesGlobal
Pet.getSpeciesGlobal(polly)  # "Parrot"

# the original way in your question
polly.getSpecies()  # "Parrot"
Pet.getSpecies(polly)   # "Parrot"

【讨论】:

    【解决方案2】:

    在 Python 中,可以将一个类视为一组属性。见下文:

    >>> class Stuff:
    ...     pi = 3.14
    ...     def foo(x, y):
    ...         return x + y
    ...     bar = lambda s: s * 2
    ...
    >>> Stuff.bar(4)
    8
    >>> Stuff.foo(5,6)
    11
    >>> Stuff.pi
    3.14
    

    在这个例子中,Stuff 只是一堆随机对象。所以Stuff.bar指的是实际功能bar。类的实例有不同的行为:当一个函数被访问时,它会自动转换为绑定方法。这意味着实例会自动作为第一个参数传递。

    当您调用Pet.getSpecies(polly) 时,polly 将作为self 参数传入。 self 没有魔法,它只是另一个参数。神奇的是当您访问polly.getSpecies 并获得<bound method Polly.getSpecies of <__main__.Polly object at 0x7f946cd14b38> 而不是<function Polly.getSpecies at 0x7f946cd1e048>

    还有@classmethod 装饰器,它接收类作为第一个参数而不是实例,并且通过明确划分类方法和实例方法使代码更易于理解。

    【讨论】:

      【解决方案3】:

      在第二个打印语句中,polly 作为 self 参数传递给类方法。这隐含在第一个 print 语句中。 在第三次打印时,调用了类方法,但没有实际的对象与数据进行操作。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-11-25
        • 2014-07-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-11-04
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多