魔术方法和定义顺序
Magic methods and definition order
我正在查看 trie implementation
的源代码
第 80-85 行:
def keys(self, prefix=[]):
return self.__keys__(prefix)
def __keys__(self, prefix=[], seen=[]):
result = []
etc.
什么是def __keys__
?那是自创的魔法物品吗?如果是这样,这是糟糕的代码吗?或者 __keys__
是否作为标准 Python 魔法方法存在?不过,我在 Python 文档中找不到它。
为什么在 def __keys__
实例化之前函数调用 self.__keys__
是合法的? 不会 def __keys__
必须在 def keys
之前(因为 keys
调用 __keys__
)?
class 在 Python 中的编译在实例化 class 之前完成。
每当创建 class 类型时,都会编译并执行 class 块的主体。然后,所有函数都被转换为绑定句柄(普通函数)或 classmethod/staticmethod 对象。然后,当创建一个新实例时,类型 __dict__
的内容被复制到该实例(并且绑定句柄被转换为方法)。
因此,在调用instance.keys()
的那一刻,实例已经同时拥有keys
和__keys__
方法。
另外,据我所知,在任何数据模式下都没有__keys__
方法。
对于你的第二个问题,这是合法的,class 的函数是在 class 定义时定义的,所以你可以确定这两个函数都会在 [=11= 之前定义] 被调用,逻辑也适用于普通函数,我们可以做 -
>>> def a():
... b()
...
>>> def b():
... print("In B()")
...
>>> a()
In B()
这是合法的,因为 a()
和 b()
都是在调用 a()
之前定义的。只有在 b()
被定义之前尝试调用 a()
才会是非法的。请注意,定义一个函数不会自动调用它,并且 python 在定义函数时不会验证函数中使用的任何函数是否已定义(直到运行时,当函数被调用时,在这种情况下它抛出一个 NameError)
关于你的第一个问题,我不知道有什么叫做 __keys__()
的魔术方法,也无法在文档中找到它。
所有真实的"magic methods"都在data model documentation; __keys__
isn't one of them. The style guide说:
Never invent such names; only use them as documented.
所以是的,组成一个新的形式是不好的形式(惯例是称它为 _keys
)。
你问题的第二部分没有意义;即使这不是 class,也无需按照调用顺序定义方法和函数。只要它们存在 实际进行调用时,这就不是问题。我倾向于在私有方法之前定义 public 方法,即使前者可能调用后者,只是为了 reader 的方便。
没有名为 __keys__()
的魔术方法,因此您怀疑这只是糟糕的命名。
class定义中的代码可以任意顺序。到下游实际调用时已经定义的所有事项。
没有名为__keys__
的魔术方法,所以它只是一个错误的命名约定。看代码,作者只是想有一个内部使用的private方法,也来自public方法keys
。如您所见,__keys__
接受一个附加参数。
关于第二个问题,你没有必要按照函数调用的顺序定义函数。它将在编译代码时可用。
我正在查看 trie implementation
的源代码第 80-85 行:
def keys(self, prefix=[]):
return self.__keys__(prefix)
def __keys__(self, prefix=[], seen=[]):
result = []
etc.
什么是
def __keys__
?那是自创的魔法物品吗?如果是这样,这是糟糕的代码吗?或者__keys__
是否作为标准 Python 魔法方法存在?不过,我在 Python 文档中找不到它。为什么在
def __keys__
实例化之前函数调用self.__keys__
是合法的? 不会def __keys__
必须在def keys
之前(因为keys
调用__keys__
)?
class 在 Python 中的编译在实例化 class 之前完成。
每当创建 class 类型时,都会编译并执行 class 块的主体。然后,所有函数都被转换为绑定句柄(普通函数)或 classmethod/staticmethod 对象。然后,当创建一个新实例时,类型 __dict__
的内容被复制到该实例(并且绑定句柄被转换为方法)。
因此,在调用instance.keys()
的那一刻,实例已经同时拥有keys
和__keys__
方法。
另外,据我所知,在任何数据模式下都没有__keys__
方法。
对于你的第二个问题,这是合法的,class 的函数是在 class 定义时定义的,所以你可以确定这两个函数都会在 [=11= 之前定义] 被调用,逻辑也适用于普通函数,我们可以做 -
>>> def a():
... b()
...
>>> def b():
... print("In B()")
...
>>> a()
In B()
这是合法的,因为 a()
和 b()
都是在调用 a()
之前定义的。只有在 b()
被定义之前尝试调用 a()
才会是非法的。请注意,定义一个函数不会自动调用它,并且 python 在定义函数时不会验证函数中使用的任何函数是否已定义(直到运行时,当函数被调用时,在这种情况下它抛出一个 NameError)
关于你的第一个问题,我不知道有什么叫做 __keys__()
的魔术方法,也无法在文档中找到它。
所有真实的"magic methods"都在data model documentation; __keys__
isn't one of them. The style guide说:
Never invent such names; only use them as documented.
所以是的,组成一个新的形式是不好的形式(惯例是称它为 _keys
)。
你问题的第二部分没有意义;即使这不是 class,也无需按照调用顺序定义方法和函数。只要它们存在 实际进行调用时,这就不是问题。我倾向于在私有方法之前定义 public 方法,即使前者可能调用后者,只是为了 reader 的方便。
没有名为
__keys__()
的魔术方法,因此您怀疑这只是糟糕的命名。class定义中的代码可以任意顺序。到下游实际调用时已经定义的所有事项。
没有名为__keys__
的魔术方法,所以它只是一个错误的命名约定。看代码,作者只是想有一个内部使用的private方法,也来自public方法keys
。如您所见,__keys__
接受一个附加参数。
关于第二个问题,你没有必要按照函数调用的顺序定义函数。它将在编译代码时可用。