鸭子类型
维基百科解释:
当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟就可以被称为鸭子。
duck typing:在程序设计中是动态类型的一种风格。在这种风格中,一个对象有效的语义,不是由继承自特定的类或实现特定的接口,而是由"当前方法和属性的集合"决定。
在鸭子类型中,关注点在于对象的行为,能作什么;而不是关注对象所属的类型。例如,在不使用鸭子类型的语言中,我们可以编写一个函数,它接受一个类型为"鸭子"的对象,并调用它的"走"和"叫"方法。在使用鸭子类型的语言中,这样的一个函数可以接受一个任意类型的对象,并调用它的"走"和"叫"方法。如果这些需要被调用的方法不存在,那么将引发一个运行时错误。任何拥有这样的正确的"走"和"叫"方法的对象都可被函数接受的这种行为引出了以上表述,这种决定类型的方式因此得名。
# 多个类实现相同的方法
class Cat(object):
def say(self):
print("i am a cat")
class Dog(object):
def say(self):
print("i am a dog")
class Duck(object):
def say(self):
print("i am a duck")
animal_list = [Cat, Dog, Duck]
for animal in animal_list:
animal().say()
Output:
i am a cat
i am a dog
i am a duck
a = ['mark1', 'mark2']
b = ['mark2', 'mark']
name_tuple = ("mark3", 'mark4')
name_set = set()
name_set.add("mark5")
name_set.add("mark6")
a.extend(b)
a.extned(name_set)
a.extend(name_tuple)
print(a)
Output:
['mark1', 'mark2', 'mark2', 'mark', 'mark6', 'mark5', 'mark3', 'mark4']
对于 extend() 方法,它并不是说要求传入一个 list,set,tuple,而是传入一个可 iterable 的对象,那么如果一个类实现了 __getitem__() 方法,是不是就可以?
def extend(self, *args, **kwargs): # real signature unknown
""" Extend list by appending elements from the iterable. """
class Company(object):
def __init__(self, employee_list):
self.employee = employee_list
# Python 本身提供的,以双下划线开始,双下划线结尾的方法,称之为魔法函数
# __getitem__ 使得该类对象可迭代
def __getitem__(self, item):
return self.employee[item]
company = Company(['tom', 'bob', 'jane'])
a.extend(company)
print(a)
Output:
['mark1', 'mark2', 'mark2', 'mark', 'mark6', 'mark5', 'mark3', 'mark4', 'tom', 'bob', 'jane']
所以看到这里,本质上 __getitem__() 和一开始的 say() 是不是有异曲同工之妙?