【问题标题】:What is happening behind the scenes when calling object.method() and Class.method(object)?调用 object.method() 和 Class.method(object) 时,幕后发生了什么?
【发布时间】:2021-02-14 19:13:09
【问题描述】:

我对 Python 很陌生,正在处理 OOP。对于何时使用对方法和类的调用,我有点困惑。下面的示例代码输出平均值,但是我很好奇您何时会从真实世界的角度使用从 Class 调用与方法调用。我很确定这只是我可能尚未解决的问题,但是对于何时使用其中一个而不是另一个有点困惑。

class Student:
    def __init__(self, new_name, new_grades):
        self.name = new_name
        self.grades = new_grades

    def average(self):
        return sum(self.grades) / len(self.grades)

student_one = Student('Test User', [70, 88, 90, 99])

# object.method()
print(student_one.average())

# Class.method(object)
print(Student.average(student_one))

【问题讨论】:

  • 它们在功能上是等效的。严格来说object.method() 是调用object 中的绑定方法。 class 调用使用未绑定的方法,但显式传入对象。如果您要处理实例状态,请始终使用 object.method()... 为 @classmethod@staticmethod 函数保留 class.method()
  • 你会一直使用student_one.average()

标签: python python-3.x oop


【解决方案1】:

在您的示例中,没有区别。 使用第一种方式。 第二种方式使您看起来好像出于某种原因需要使用“后门”,例如,如果 student_one 实际上不是 Student 实例,但您想要专门调用Student类的average方法。

如果有经验的 Python 开发人员阅读您的代码,看到Student.average(student_one) 可能会让他们停顿片刻,想知道为什么作者要在这里使用未绑定的average。这将是一种不同寻常的风格,也许暗示可能会发生一些比实际情况更微妙的事情——一个绊脚石。

对于幕后发生的事情,第一种方式使用bound method,第二种方式只使用普通的function

>>> Student.average
<function __main__.Student.average(self)>
>>> student_one.average 
<bound method Student.average of <__main__.Student object at 0xcafef00d>>

绑定方法只是一个通过descriptor protocol*绑定到实例的函数,并且实例(“self”)作为第一个位置参数隐式传递:

>>> student_one.average.__self__ is student_one 
True
>>> student_one.average.__func__ is Student.average 
True

通过在类上使用函数并显式传入实例,您基本上可以执行与调用描述符自动执行的操作相同的操作。

要更深入地了解什么是方法,请参阅文档 here 中有关此绑定过程的详细文档。

* 只是通过“.”来表达的一种奇特方式。即虚线属性访问

【讨论】:

  • “后门”的解释很有帮助。因此,如果有任何实例需要我访问平均方法(也许对那些不是学生的人进行类似的计算),我似乎只想从课堂上调用。 object.method() 就是这样!
  • @AntonioSaqueton 是的,你明白了。
猜你喜欢
  • 2016-02-23
  • 1970-01-01
  • 1970-01-01
  • 2011-10-19
  • 1970-01-01
  • 2011-07-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多