鸭子类型:When I see a bird that walks like a duck and swims like a duck and quacks like a duck, I call that bird a duck. (可以查看维基百科)
当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟就可以被称为鸭子。
鸭子类型是动态类型的一种风格,不是由继承特定的类或实现特定的接口,而是当前的方法和属性的集合决定,也就是说我们并不关心对象是什么类型,到底是不是鸭子,只关心行为。python崇尚鸭子类型,类与类之间不用共同继承一个父类,只需要将它们做得像一种事物即可。
静态语言和动态语言:
静态类型语言在编译时便已确定变量的类型,而动态类型语言的变量类型要到程序运行的时候,待变量被赋予某个值之后,才会具有某种类型。
静态类型语言的优点首先是在编译时就能发现类型不匹配的错误,编辑器可以帮助我们提前避免程序在运行期间有可能发生的一些错误。其次,如果在程序中明确地规定了数据类型,编译器还可以针对这些信息对程序进行一些优化工作,提高程序执行速度。
静态类型语言的缺点首先是迫使程序员依照强契约来编写程序,为每个变量规定数据类型,归根结底只是辅助我们编写可靠性高程序的一种手段,而不是编写程序的目的,毕竟大部分人编写程序的目的是为了完成需求交付生产。其次,类型的声明也会增加更多的代码,在程序编写过程中,这些细节会让程序员的精力从思考业务逻辑上分散开来。
动态类型语言的优点是编写的代码数量更少,看起来也更加简洁,程序员可以把精力更多地放在业务逻辑上面。虽然不区分类型在某些情况下会让程序变得难以理解,但整体而言,代码量越少,越专注于逻辑表达,对阅读程序是越有帮助的。
动态类型语言的缺点是无法保证变量的类型,从而在程序的运行期有可能发生跟类型相关的错误。
动态类型语言对变量类型的宽容给实际编码带来了很大的灵活性。由于无需进行类型检测,我们可以尝试调用任何对象的任意方法,而无需去考虑它原本是否被设计为拥有该方法。
例1:
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 = Cat # 变量可以指向任何类型,是引用,动态语言的灵活性
animal().say()
例2:
# 以下用python模拟java里的用法
class Animal:
def say(self):
print('i am a animal')
class Cat(Animal):
def say(self):
print('i am a cat')
Animal an = Cat() #在java中要指定变量类型,子类要继承父类,在python中不用
an.say()
在例1中,Cat、Dog、Duck不用继承某个父类,只需要实现一个共同的方法,即上面所说的行为,这些类就可以归为一种类型
例3:
class Company(object):
def __init__(self, employee_list):
self.employee = employee_list
def __getitem__(self, item):
return self.employee[item]
def __len__(self):
return len(self.employee)
company Company(['tom', 'bob', 'jane'])
name_list=['bobby1', 'bobby2']
name_list2=['bobby3', 'bobby4']
name_tuple = ('bobby5', 'bobby6')
name_set = set()
name_set.add('bobby7')
name_set.add('bobby8')
a.extend(b) # b只需要是一个可迭代对象iterable,如tuple,list,set,生成器等
a.extend(company)
print(a)
extend函数接收的参数是可迭代对象iterable, 它接收的参数不限定具体类型,只要是可迭代的都可以,这就是鸭子类型的概念,这也是动态语言的灵活之处
company实现__getitem__方法后就变成了可迭代对象(魔法方法的作用,可以参考https://blog.csdn.net/f1ngf1ngy1ng/article/details/80367581),事实上,__getitem__等魔法方法也运用了鸭子类型概念,只要类中实现了这个__getitem__方法,不需要其他继承等额外的条件,就可以增强类的类型,使类成为可迭代类型