在谈论类方法前,我们先理解几个概念:
- 鸭子类型
- 协议
鸭子类型
python是动态的面向对象语言,动态意味着只有在运行时才能确定对象的类型,面向对象语言意味着带有面向对象的三大特性(继承、封装、多态)。
那么我们如何认定一个对象的类型呢?
我们不关注对象的类型,而是关注对象的方法(行为)。
如果它的行为是鸭子的行为,那么就可以认为它是鸭子。
协议
概括来讲,协议是让python这种动态语言实现多态的方式。
简单来说,协议是一组方法,当我们在类中实现了特定的方法,也就是遵守了协议。
结合我们刚刚讲的“鸭子类型”来看,“如果它的行为是鸭子的行为,那么就可以认为它是鸭子。”。
举个例子,比如我有一个图书馆,有三本书,那么我如何迭代他们呢?
中心思想:我应该在类中实现getitem方法。
class Library(object):
def __init__(self):
self.books = [{'book1': 'a'}, {'book2': 'b'}, {'book3': 'c'}]
def __getitem__(self, index):
print("index:{}".format(index))
return self.books[index]
getitem方法其实就是告诉Library对象如何获取book。
然后我们遍历一下。
library = Library()
for book in library:
print(book)
image.png
总结一下这个例子:
我们通过getitem方法,让Library对象可被迭代,python中的很多魔法方法(双下滑线开始和结尾的方法)都有类似的功效。
那么,接下来我们一个一个来测试,不断探索python中的魔法方法。
_init_ & _new_
init和new方法会在一个对象创建和初始化的时候调用,二者有紧密的联系。
从对象的声明周期来看,在创建对象阶段,首先会调用new方法,他会开辟内存,建立实例对象与内存的联系。
然后调用init方法,对创建了对象进行赋值。
比如下面的例子:
class Test:
def __init__(self, value):
self.value = value
print("调用了init方法")
def __new__(cls, *args, **kwargs):
print("调用了new方法")
return super(Test, cls).__new__(cls)
t = Test('value')
print(t.value)
image.png
需要注意,由于new方法是对象的构造方法,所以需要return一个实例,这个实例是由super方法生成的实例并调用了new方法得来的。
未完待续。。。
网友评论