我刚刚研究了静态语言中的协方差和逆变(更具体地说是C#)。这个概念对我来说相当清楚,但我对如何应用于像Python这样的动态语言有疑问。
由于Python是鸭子类型(或结构类型),在我看来,在这种语言中甚至没有方差和协方差的概念吗?
如果我没有误会,那么在编译时用C#这样的语言检查逆变和协方差之类的东西,这是可能的,因为变量有一个类型,它绑定的值也有一个类型,这些必须匹配或是co(ntra) - 或不变的。但是,由于在编译时没有使用像Python这样的语言进行打字的概念,我不知道如何应用这个概念。
有什么想法吗?
我的想法: 协方差的概念意味着每当我们期望一种X类型时,X的任何子类都会这样做。因此,在Python中没有出现,因为没有类型检查来执行此操作。发生的唯一检查是否是对象通过方法和属性具有必要的实现。
在C#中,例如我们有一个方法:
void DoStuff(Person p)
{
p.Dance();
};
我们可以使用Student的实例调用此方法(如果这是Person的子类)。
现在,在Python中,我们可以很好地传递一个Bird对象,该对象在继承层次结构中不会以任何方式与Person相关(除了它也会从对象继承),只要这只鸟实现{{1 }}
这就是我问这个概念的原因。根据我的理解,Python是协变的和逆变的..好吧,一切?
答案 0 :(得分:3)
实际上,这并不完全(我的理解)方差。方差是关于构造函数类型的行为,例如C#中的泛型。使用Student
代替Person
是普通的子类型。使用List<Student>
代替Lis<Person>
是主语或协方差和逆差。
至于实际问题:嗯,Python没有静态类型系统,因此没有像类型构造函数这样的概念。语言根本不关心这些事情。它只是继续并允许你传递的任何值,如果它工作,那很好。
然而,方差的概念在任何具有子类型和非原子值效应的语言中都非常有用。例如,虽然没有List<Person>
,但你可能(没有说出语言,因为语言甚至没有开始考虑这些事情)建立一些不变量:
students
必须只包含Student
个对象(或隐含符合Person
接口的对象,以便进行鸭子输入。)print_persons
提供Person
个对象的列表并且只读取它add_person
提供Person
个对象的列表并添加到其中使用与静态语言相同的推理,您可以看到print_persons(students)
正确而add_person(students)
可能不正确。