返回介绍

7.2 Python 中方法的运行机制

发布于 2024-01-23 21:41:46 字数 2421 浏览 0 评论 0 收藏 0

在此之前你可能已经写过很多方法但从未多想,但为了理解装饰器的行为,你就需要知道方法背后的运行机制。

方法是指作为类属性保存的函数。让我们来看一下当直接访问这样一个属性时到底发生了什么。在Python 2中情况如示例7.5所示,在Python 3中情况如示例7.6所示。

示例 7.5  Python 2 的方法

>>> class Pizza(object):
...   def __init__(self, size):
...     self.size = size
...   def get_size(self):
...     return self.size
...
>>> Pizza.get_size
<unbound method Pizza.get_size>

Python 2会提示get_size属性是类Pizza的一个未绑定方法。

示例 7.6 Python 3 的方法

>>> class Pizza(object):
...   def __init__(self, size):
...     self.size = size
...   def get_size(self):
...     return self.size
...
>>> Pizza.get_size
<function Pizza.get_size at 0x7fdbfd1a8b90>

Python 3中已经完全删除了未绑定方法这个概念,它会提示get_size是一个函数。

两种情况的本质是一样的:get_size是一个并未关联到任何特定对象的函数,如果试图调用它的话,Python会抛出错误(在Python 2中情况如示例7.7所示,在Python 3中情况如示例7.8所示)。

示例 7.7 在 Python 2 中调用未绑定的get_size

>>> Pizza.get_size()
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
TypeError: unbound method get_size() must be called with Pizza instance as first argument (got nothing instead)

示例 7.8 在 Python 3 中调用未绑定的get_size

>>> Pizza.get_size()
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
TypeError: get_size() missing 1 required positional argument: 'self'

Python 2中拒绝该方法调用是因为它是未绑定的。Python 3允许调用,但会提示未提供必需的self参数。这使得Python 3更加灵活,不仅可以向方法传入该类的任意实例,还可以传入任何对象,只要它包含方法期望的属性:

>>> Pizza.get_size(Pizza(42))
42

尽管不太方便,但它能运行:每次调用类的一个方法都要对该类进行引用。

所以Python通过将类的方法绑定给实例为我们完成了后续工作。换句话说,可以通过任何Pizza访问get_size方法,进一步说,Python会自动将对象本身传给方法的self参数,如示例7.9所示。

示例 7.9  调用绑定的get_size

>>> Pizza(42).get_size
<bound method Pizza.get_size of <__main__.Pizza object at 0x7f3138827910>>
>>> Pizza(42).get_size()
42

不出所料,不需要传入任何参数给get_size,因为它是绑定方法:它的self参数会自动设置为Pizza的实例。下面是一个更好的例子:

>>> m = Pizza(42).get_size
>>> m()
42

一旦有了对绑定方法的引用则无需保持对Pizza对象的引用。如果有了对方法的引用但是想知道它被绑定到了哪个对象,可以查看方法的__self__属性:

>>> m = Pizza(42).get_size
>>> m.__self__
<__main__.Pizza object at 0x7f3138827910>
>>> m == m.__self__.get_size
True

显然,仍然可以保持对对象的引用,并随时在需要的时候访问它。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文