我在练习基本python脚本时从网站上找到了以下代码。从下面的代码我能够理解类和实例以及第一个print语句。
但我不理解第二和第三个印刷语句背后使用的概念。如何将一个实例(在下面的代码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)
答案 0 :(得分:1)
在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
装饰器,它接收类作为第一个参数而不是实例,并通过明确分隔类方法和实例方法使代码更容易理解。
答案 1 :(得分: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 :(得分:0)
在第二个print语句中,polly作为self方法传递给class方法。这在第一个印刷声明中隐含地发生。 在第三个打印件上,调用类方法,但没有实际对象可以处理数据。