What is happening behind the scenes when calling object.method() and Class.method(object)?

一笑奈何 提交于 2020-11-29 02:35:18

问题


I am pretty new to Python and am tackling OOP. I am a bit confused as to when to use calls to methods and classes. The sample code below outputs the average, however I am curious as to when you would use calling from the Class vs methods from a real-world perspective. I'm pretty sure this is just something that I may have yet to tackle, but it's just been a bit of a confusion as to when I would use one over the other.

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))

回答1:


In your example, there is no difference. Use the first way. The second way makes it appear as though you need to use "the back door" for some reason, for example if student_one was not actually a Student instance but you wanted to specifically call the average method of the Student class.

If an experienced Python developer were to read your code, seeing Student.average(student_one) may make them pause for a moment and wonder why the author wants to use the unbound average here. It would be an unusual style, and perhaps could imply that there may be something more subtle happening than there really was - a stumbling block.

For what's going on behind the scenes, the first way uses a bound method and the second way just uses a normal function.

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

A bound method is just a function which is bound to an instance, via descriptor protocol*, and the instance ("self") is passed as the first positional argument implicitly:

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

By using the function on the class and passing in the instance explicitly, you essentially do the same thing as an invocation of the descriptor does automatically.

For a deeper understanding of what a method is, there's detailed documentation of this binding process in the docs here.

* Just a fancy way of saying via the "." i.e. the dotted attribute access



来源:https://stackoverflow.com/questions/54680513/what-is-happening-behind-the-scenes-when-calling-object-method-and-class-metho

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!