Python 魔术方法与定义顺序
我正在看一个 在第80-85行:Python 魔术方法与定义顺序,python,trie,magic-methods,Python,Trie,Magic Methods,我正在看一个 在第80-85行: def keys(self, prefix=[]): return self.__keys__(prefix) def __keys__(self, prefix=[], seen=[]): result = [] etc. 什么是def\uuuuuuu键?那是一个自创的神奇物体吗?如果是这样,这是一个糟糕的代码吗?或者,\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
def keys(self, prefix=[]):
return self.__keys__(prefix)
def __keys__(self, prefix=[], seen=[]):
result = []
etc.
def\uuuuuuu键?
那是一个自创的神奇物体吗?如果是这样,这是一个糟糕的代码吗?或者,\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
是否作为标准的Python魔术方法?但是,我在Python文档中找不到它self.\uuuukeys\uuuuu
在def\ukeys\uuuu
被实例化之前是合法的?难道def\ukeys\uuuuu
不必须在def keys
之前调用吗
Python中类的编译是在类实例化之前完成的 无论何时创建类类型,都会编译并执行类块的主体。然后,将所有函数转换为绑定句柄(普通函数)或classmethod/staticmethod对象。然后,当创建一个新实例时,类型的
\uuuu dict\uuuu
的内容被复制到实例中(绑定句柄被转换为方法)
因此,在调用instance.keys()
时,实例已经同时具有键
和键
方法
而且,据我所知,在任何数据模式下都没有
\uuuuuuuuuuuuuuuuuuuuuuuu键
方法 对于第二个问题,它是合法的,类的函数是在定义类时定义的,因此您可以确保在调用keys()
之前定义这两个函数,逻辑也适用于普通函数,我们可以这样做-
>>> def a():
... b()
...
>>> def b():
... print("In B()")
...
>>> a()
In B()
这是合法的,因为a()
和b()
都是在调用a()
之前定义的。只有在定义b()
之前尝试调用a()
,这才是非法的。请注意,定义函数不会自动调用它,python也不会在定义函数时验证函数中使用的任何函数是否已定义(直到运行时,函数被调用时,在这种情况下会抛出NameError)
对于你的第一个问题,我不知道有任何这样的神奇方法叫做\uuuukeys\uuuu()
,在文档中也找不到<代码>\uuuu键\uuuu不是其中之一。报告说:
永远不要捏造这样的名字;仅按文件规定使用
因此,是的,编一个新的是一种糟糕的形式(传统上称之为\u keys
)
你问题的第二部分没有意义;即使这不是一个类,也不需要按调用顺序定义方法和函数。只要他们在实际通话时还存在,这就不是问题。我倾向于先定义公共方法,再定义私有方法,尽管前者可能会调用后者,只是为了方便读者
\uuuu keys\uuuu()
的神奇方法,所以正如您所怀疑的,这只是一个糟糕的命名没有名为
\uuuuuuuuuuuuuuuuuuuuuuuu键
的神奇方法,因此它只是一个错误的命名约定。查看代码,作者只想拥有一个内部使用的私有方法,也可以使用公共方法keys
。正如您所看到的,\uuuuuu键
接受一个附加参数
关于第二个问题,没有必要按照调用函数的顺序定义函数。它将在编译代码时可用
def keys
定义了keys
函数,在有人调用它之前,它实际上不会调用self.\uuu keys\uuu
,例如trie.keys()
。到那时,\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu键
已经定义好了。当应用到新样式类(Python 3中唯一的一种)时,您对对象创建方式的描述不是很准确。虽然链接类没有对象
作为基础,但它可能应该这样做!在新样式的类中,定义的函数不会转换为任何特殊的函数(除非它们经过修饰)。只有在查找实例时,它们才会被绑定(通过描述符协议)。此外,没有任何内容从类\uuuuu dict\uuuu
复制到实例的\uuuu dict\uuuu
,因为属性查找将在必要时检查类dict(以及任何基的dict)。@Blckknght据我所知,所有内容仍然复制到实例,因为如果尝试使用类变量,您可以修改实例中的副本,而无需修改类变量。此外,在python2中,即使使用新样式的类,函数也会变为绑定对象(Foo.method是一个绑定函数,因为它要求Foo作为第一个参数)。不会自动将任何内容复制到实例dict中。您的“修改”类变量可能会反弹为实例变量,从而使其隐藏旧值,而不是在适当的地方进行修改。关于方法,在Python2中,当您在类上查找一个方法时,会得到一种特殊的“未绑定”方法,这在一定程度上是正确的,但在这种情况下,您是错误的。只有在执行查找时,才会发生绑定。如果查看类\uuuu dict\uuuu
,您将看到未修改的函数。