7.2 Python 中方法的运行机制
在此之前你可能已经写过很多方法但从未多想,但为了理解装饰器的行为,你就需要知道方法背后的运行机制。
方法是指作为类属性保存的函数。让我们来看一下当直接访问这样一个属性时到底发生了什么。在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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论