Python简单class理解

Python simple class understanding

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

但是我不明白第二个和第三个打印语句背后使用的概念。如何将实例(在下面的代码 polly 中)作为参数传递给 class 的方法? 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)

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

在Python中,一个class可以看作是一个属性包。见下文:

>>> 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。 class 的实例具有不同的行为:访问函数时,它会自动转换为绑定方法。这意味着该实例会自动作为第一个参数传递。

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

还有 @classmethod 装饰器,它接收 class 作为第一个参数而不是实例,并且通过清楚地分隔 class 方法和实例方法。

其实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"