简体   繁体   English

为什么csv.reader不被认为是一个类?

[英]Why is csv.reader not considered a class?

From my understanding, an object is an instance of a class. 根据我的理解,对象是类的实例。 So since csv.reader creates a reader object, I thought that it would be considered a class. 因此,由于csv.reader创建了一个reader对象,我认为它将被视为一个类。 I'm pretty new to this, so it would be helpful if someone could clarify this for me. 我对此很陌生,所以如果有人能为我澄清这一点会很有帮助。

If something is an object, it's generally not a class It's like with animal species. 如果某物是物体,它通常不是一类它就像动物物种一样。

The dog named Cujo is of the species Dog, but Cujo isn't the species (category) itself. 名为Cujo的狗属于犬种,但Cujo不是物种(类别)本身。 You can create a dog eg by: 你可以创建一只狗,例如:

dog = Dog ('Cujo')

I can have the class Dinosaur, but there are no living objects of that class around anymore. 我可以上恐龙课,但是那个班的周围没有生物。

Not only classes can return objects. 类不仅可以返回对象。 I can have a function as follows: 我可以有如下功能:

def dog_factory (name):
    return Dog (name)

To create a dog with that, you can state: 要用它创建一只狗,你可以说:

dog = dog_factory ('Cujo')

While Dog is a class, dog_factory is just a function. 虽然Dog是一个类,但dog_factory只是一个函数。 It uses the class to create a dog. 它使用该类来创建一条狗。

If you ask for the class, using type (dog) , you'll see that dog is of class Dog, not of class dog_factory. 如果你要求上课,使用type (dog) ,你会看到狗是类Dog,而不是类dog_factory。

Don't be confused by the situation in JavaScript, if you happen to know that. 如果您碰巧知道这一点,请不要被JavaScript中的情况所迷惑。 Truly class-based languages like C++, Java, C# and Python are quite different, and in my view less contorted. 真正基于类的语言,如C ++,Java,C#和Python是完全不同的,在我看来,扭曲程度较低。

Not everything that creates an object is a class. 并非创建对象的所有东西都是一个类。 Most callables that create objects aren't classes, and every callable returns an object unless it doesn't return anything at all (by throwing an exception, for example). 创建对象的大多数可调用对象都不是类,并且每个可调用对象都返回一个对象,除非它根本不返回任何内容(例如,通过抛出异常)。 For example, 例如,

def f():
    return []

creates and returns a list object, but it's not a class. 创建并返回一个列表对象,但它不是一个类。

As for why csv.reader specifically wasn't written to be a class, that seems to be an artifact of the historical development of the csv module. 至于为什么csv.reader没有特别编写为类,这似乎是csv模块历史发展的工件。 The original PEP proposing the module says reader should be a function: 提出模块的原始PEPreader应该是一个功能:

CSV readers are created with the reader factory function 使用阅读器工厂功能创建CSV阅读器

but that just shifts the question from "why is reader not a class" to "why does the PEP say it shouldn't be a class", and the PEP doesn't give a rationale. 但这只是将问题从“为什么reader不是一个阶级”转移到“为什么PEP说它不应该是一个阶级”,并且PEP没有给出理由。

One possibility is to allow the factory function to return multiple reader types, although that doesn't seem to have ever been explored. 一种可能性是允许工厂功能返回多种读卡器类型,尽管似乎从未探索过。 Another hypothesis is that the module descends from code so old it had to use a factory function. 另一个假设是模块从代码中下降,因此必须使用工厂函数。

csv.reader returns instances of a reader type written in C , and the CSV PEP suggests that the code may be based on an earlier C module so old it predates type-class unification . csv.reader返回用C编写的读者类型的实例,而CSV PEP建议代码可能基于早期的C模块,因为它早于类型级统一 Back before type-class unification, types written in C couldn't be called directly. 在类型级别统一之前, 无法直接调用用C编写的类型。 You had to write a factory function to create instances of C types. 必须编写工厂函数来创建C类型的实例。 This even extended to built-in types like list and int ; 这甚至扩展到了像listint这样的内置类型; back then, names like list and int were instead factory functions that created list and int objects, rather than referring to the types themselves. 那时候,像listint这样的名字就是创建list和int对象的工厂函数,而不是引用类型本身。

In Python 2.2, type-class unification made C types callable, but code designed with the earlier system in mind would still have factory functions and not necessarily any compelling reason to get rid of them. 在Python 2.2中,类型级统一使C类型可以调用,但是使用早期系统设计的代码仍然具有工厂函数,并不一定有任何令人信服的理由去除它们。

From the PEP 305 : PEP 305

CSV readers are created with the reader factory function: 使用阅读器工厂功能创建CSV阅读器:

obj = reader(iterable [, dialect='excel']
             [optional keyword args])

So csv.reader itself is technically a function , and not a class. 所以csv.reader本身在技术上是一个函数 ,而不是一个类。

You might think it would make more sense if csv.reader was a class, and isinstance(my_reader, csv.reader) returned True , and I'd agree with you. 如果csv.reader是一个类,并且isinstance(my_reader, csv.reader)返回True ,你可能会觉得更有意义,我同意你的isinstance(my_reader, csv.reader) That's how csv.DictReader does it: 这就是csv.DictReader作用:

>>> import io, csv
>>> reader = csv.DictReader(io.StringIO())
>>> isinstance(reader, csv.DictReader)
True

Unfortunately, the CPython code which defines the reader type and exposes it to the csv.py module was not carefully designed to be consistent with such conventions. 不幸的是,定义读者类型并将其暴露给csv.py模块的CPython代码并未经过精心设计,无法与此类约定保持一致。 Instead, csv imports the name reader from a _csv module , which is distributed as compiled code from an .so (binary) file. 相反, csv_csv模块导入名称reader ,该模块作为编译代码从.so(二进制)文件中分发。 Historically, the all lowercase name referred to a C type , which explains the name _csv.reader instead of _csv.Reader . 从历史上看, 全部小写名称是指C类型 ,它解释了名称_csv.reader而不是_csv.Reader

Internally, a csv reader is an instance of the type(_csv.reader(...)) class, and that class itself is not exposed. 在内部,csv reader是type(_csv.reader(...))类的实例,并且该类本身不会公开。 So if you want to type-check it, you would need to do something hacky like this: 因此,如果你想要进行类型检查,你需要做一些像这样的hacky:

>>> import io, csv
>>> csv.Reader = type(csv.reader(io.StringIO()))
>>> isinstance(csv.reader(io.StringIO()), csv.Reader)
True

There's no particular reason the library developers couldn't have made the class public and called it csv.Reader , but that's not what happened. 没有特别的原因,库开发人员不能将该类公开并称之为csv.Reader ,但事实并非如此。 The csv module is about 15 years old at this time, and it predates the cleanup of Python's object model, when the naming conventions for types and classes had time to become better established. csv模块目前大约有15年的历史,它早于Python对象模型的清理,当类型和类的命名约定有时间变得更好时。

Unfortunately, changing the interface from a csv.reader factory function into a csv.Reader class would break backwards compatibility. 不幸的是,将接口从csv.reader工厂函数更改为csv.Reader类会破坏向后兼容性。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM