在python中,当调用类的对象时,类的引用和它的对象/实例之间的功能区别是什么?



我正在寻找作为默认类和函数参数存在的默认参数object, self的含义,因此远离它,如果我们调用类的属性,我们应该使用Foo(类引用)还是应该使用Foo()(类的实例)。

如果你是阅读一个正常的属性,那么这并不重要。如果您要绑定一个普通属性,那么您必须使用正确的属性才能使代码正常工作。如果你要访问一个描述符,那么你必须使用实例。

python类语义的细节在数据模型中有很好的文档。特别是__get__语义在这里起作用。实例基本上是将它们的命名空间堆叠在类的命名空间之上,并添加一些用于调用方法的样板文件。


这里有一些很大的"这取决于你在做什么"的陷阱。最重要的问题是:您想访问还是实例属性?第二,你想要属性还是方法?

让我们举个例子:

class Foo(object):
  bar = 1
  baz = 2
  def __init__(self, foobar="barfoo", baz=3):
    self.foobar = foobar
    self.baz = baz
  def meth(self, param):
    print self, param
  @classmethod
  def clsmeth(cls, param):
    print cls, param
  @staticmethod
  def stcmeth(param):
    print param

这里,bar是一个属性,所以你可以通过Foo.bar获得它。由于实例对其类名称空间具有隐式访问,因此也可以将其作为Foo().bar获取。foobar是一个实例属性,因为它从来没有绑定到类(只有实例,即self s) -你只能得到它作为Foo().foobar。最后,baz一个类和一个实例属性。默认为Foo.baz == 2Foo().baz == 3,因为类属性被__init__中的实例属性集隐藏。

同样,在赋值操作中,处理类还是处理实例也有细微的区别。Foo.bar=2将设置class属性(也适用于所有实例),而Foo().bar=2创建一个实例属性,该实例属性为该特定实例遮蔽class属性。

对于方法来说,情况有点类似。然而,这里您获得了实例方法的隐式self参数(如果是为类定义的函数)。基本上,调用Foo().meth(param=x)被静默地转换为Foo.meth(self=Foo(), param=x)。这就是为什么调用Foo.meth(param=x)通常是无效的——meth没有"绑定"到实例,因此缺少self参数。

现在,有时您不需要方法中的任何实例数据—例如,您有严格的字符串转换,这是一个更大的解析器类的实现细节。这就是@classmethod@staticmethod发挥作用的地方。类方法的第一个参数始终是类,而不是常规方法的实例。Foo().clsmeth(param=x) Foo.clsmeth(param=x)导致呼叫clsmethod(cls=Foo, param=x)。这里,这两个是等价的。更进一步,静态方法不获取任何类或实例信息—它就像绑定到类名称空间的原始函数。

最新更新