大多数人可能都很熟悉,这是来自Mark Pilgrim的书DIP,第5章
class FileInfo(UserDict):
"store file metadata"
def __init__(self, filename=None):
UserDict.__init__(self)
self["name"] = filename
嗯,我是python的新手,来自基本的C背景,并且对它有困惑。在我不明白之前陈述我的理解。
声明0:FileInfo
继承自班级UserDict
声明1:__init__
不是构造函数,但是在类实例化之后,这是定义的第一个方法。
Statement2:self
几乎与this
现在麻烦了: 根据St1 init定义为第一个函数。
UserDict.__init__(self)
现在在同一个函数__init__
中为什么函数被引用,我猜没有固有的递归。或者它是否尝试覆盖类__init__
继承的类UserDict
的{{1}}方法,并添加文件名的额外参数(键值对)并将其引用到文件名为传递给FileInfo
方法。
我部分肯定,我已经回答了我的问题,但是因为你可以感觉到存在混淆,如果有人可以解释我如何通过一些更高级的用例和一般代码的详细示例来解释这种混乱,那将会很棒是写的。
答案 0 :(得分:4)
你是对的,__init__
方法不是构造函数,它是在实例化对象后调用的初始化程序。
在您提供的代码中,__init__
类上的FileInfo
方法正在扩展基类__init__
方法的功能UserDict
。通过调用基类__init__
方法,它执行基类初始化中的任何代码,然后添加自己的代码。如果不调用基类的__init__
方法,则只会调用显式添加到FileInfo
的{{1}}方法的代码。
执行此操作的传统方法是使用__init__
方法。
super
常见用例是返回额外值或添加其他功能。在Django基于类的视图中,方法class FileInfo(UserDict):
"store file metadata"
def __init__(self, filename=None):
super(UserDict, self).__init__()
self["name"] = filename
用于获取用于呈现模板的数据字典。因此,在扩展方法中,您将获得从base方法返回的任何值,然后添加自己的值。
get_context_data
这样,当你想扩展它时,你不需要重新实现基本方法的功能。
答案 1 :(得分:4)
在Python中创建对象分为两步:
__new__(self, ...)
#constructor
__init__(self, ...)
#initializer
__new__
负责创建对象,主要在对象应该是不可变的时候使用。
__init__
之后调用 __new__
,并进行任何进一步的配置。由于Python中的大多数对象都是可变的,因此通常会跳过__new__
。
self
指的是有问题的对象。例如,如果您有d = dict(); d.keys()
,则在keys
方法self
中会引用d
,而不是dict
。
当子类具有与其父类同名的方法时,Python调用子类'方法并忽略父类;因此,如果需要调用父方法,则子类方法必须调用它。
答案 2 :(得分:0)
__ init__不是构造函数,但是在类实例化之后,这是第一个定义的方法。
在__new__
之后(即当您调用ClassName()
时)初始化实例时调用此方法。我不确定与构造函数相比有什么区别。
声明2:自我几乎就是这样
是的,但它不是语言结构。名称self
只是惯例。传递给实例方法的第一个参数始终是对类实例本身的引用,因此编写self只是为了命名它(将它赋给变量)。
的UserDict .__初始化__(个体)
在这里,您调用UserDict的__init__
方法并向其传递对新实例的引用(因为您没有使用self.method_name
调用它,它不会自动传递。您不能调用继承的类构造函数,不引用其名称,或使用super
)。所以你正在做的是初始化你的对象,就像初始化任何UserDict对象一样。
答案 3 :(得分:0)
“或者它是否尝试覆盖类FileInfo继承的类UserDict的init方法,并添加了一个额外的filename参数(键值对)并将其引用到传递给init方法的文件名。”
就是这样。 UserDict.__init__(self)
调用超类init方法。
由于你来自C,也许你对OOP没有很好的经验,所以你可以阅读这篇文章:http://en.wikipedia.org/wiki/Inheritance_(object-oriented_programming)以更好地理解继承原则(以及我使用的“超类”术语)。 p>
答案 4 :(得分:0)
当您为从基类继承的类调用__init__
方法时,通常会修改祖先类,并且作为自定义的一部分,您可以使用适当的参数扩展祖先的init方法。
答案 5 :(得分:0)
FileInfo的__init__
方法覆盖了__init__
的{{1}}方法。
然后UserDict
在新创建的FileInfo.__init__
实例(自我)上调用UserDict.__init__
。这样,FileInfo
实例可以使用UserDict
可用的所有属性和魔法(即,它们都是从FileInfo
继承的。)
最后一行是覆盖UserDict
的原因:UserDict不会创建所需的属性UserDict.__init__
。
答案 6 :(得分:0)
..自变量表示对象本身的实例。在python中,这不是其他语言中的隐藏参数。你必须明确声明它。当您创建FileInfo类的实例并调用其方法时,它将自动传递,
__init__
方法大致代表Python中的构造函数。