我刚刚研究了静态语言(更具体地说是 C#)中的协变和逆变。这个概念对我来说相当清楚,但我对如何将其应用于像 Python 这样的动态语言持怀疑态度。
由于Python是鸭子类型(或结构类型),在我看来,这种语言甚至没有方差和协方差的概念?
如果我没记错的话,像逆变和协变之类的事情会在 C# 等语言的编译时进行检查,这是可能的,因为变量具有类型,并且它绑定(bind)到的值也具有类型,并且这些必须匹配或者是共(ntra)-或不变的。然而,由于像 Python 这样的语言没有在编译时键入的概念,所以我不知道如何应用这个概念。
有什么想法吗?
我的想法: 协方差的概念意味着每当我们期望 X 的类型时,X 的任何子类也会如此。所以,在 Python 中这不会出现,因为没有类型检查来执行此操作。唯一进行的检查是对象是否通过方法和属性实现了必要的实现。
例如,在 C# 中,我们有一个方法:
void DoStuff(Person p)
{
p.Dance();
};
我们可以很好地使用 Student 的实例调用此方法(如果这是 Person 的子类)。
现在,在Python中,我们可以很好地传入一个在继承层次结构中与Person没有任何关系的Bird对象(除非它也继承自object),只要这个鸟实现了舞蹈()
.
这就是我询问这个概念的原因。据我了解,Python 在……一切事物中都是协变和逆变的?
最佳答案
实际上,这并不完全是(我的理解)方差。方差与类型构造函数的行为有关,例如 C# 中的泛型。使用Student
代替Person
是普通的子类型。使用List<Student>
代替Lis<Person>
是主语或协变和逆变。
至于实际问题:Python 没有静态类型系统,因此没有类型构造函数之类的概念。语言根本不关心这些事情。它只是继续并允许您传递任何值,如果它有效,那就太好了。
但是,方差的概念在任何具有子类型和非原子值效果的语言中都非常有用。例如,虽然没有List<Person>
,您可能(无需告诉语言,因为语言甚至没有开始考虑这些事情)建立一些不变量:
- 一些列表
students
必须仅包含Student
对象(或隐式符合Person
接口(interface)的对象,为了鸭子类型)。 - 一些功能
print_persons
必须给出Person
的列表对象并且只读取它 - 一些功能
add_person
必须给出Person
的列表对象并添加到其中
使用与静态语言相同的推理,您可以看到 print_persons(students)
是正确的,而 add_person(students)
可能不正确。
关于c# - Python 中的参数可以是逆变的还是协变的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21023176/