所以这是我的情况。我有一个班级ABCAdapter。在这里,我已经宣布了一系列方法,我们之间有:
@staticmethod
def __prepare_param_names(attributes_list, prefix = None):
....some processing....
现在来自另一个类,即我做的FlowService:
from tvb.core.adapters.abcadapter import ABCAdapter
...other imports and code...
def prepare_adapter(self, project_id, adapter_module, adapter_name):
...some more code here...
interface = adapter_instance.get_attribute_list()
interface = ABCAdapter.__prepare_param_names(interface)
...some more code here...
现在,在使用以下方法调用静态方法时失败:
AttributeError: type object 'ABCAdapter' has no attribute '_FlowService__prepare_param_names'
到目前为止,我还没有使用过静态方法,所以这里的诀窍是什么?
此致 波格丹
答案 0 :(得分:4)
您可能知道,Python不强制实施受保护/私有属性:所有类属性都是全局可访问的。但是,有一个约定,其名称以至少一个_
开头的属性是实现细节,而不是公共API的一部分。
双重强制名称是用于following use case的轻微破解。假设你有
class Mapping:
def __init__(self, iterable):
self.update(iterable)
def update(self, iterable):
<stuff>
class MappingSubclass(Mapping):
def update(self, keys, values):
<stuff>
请注意,Mapping
定义了一个方法update
,该方法在__init__
中调用。然后,子类使用不同的签名重新定义 update
。由于在重写Mapping
方法时,子类的初始化继承自update
,因此在运行时会导致错误。
为避免这种情况,您希望Mapping
的{{1}}副本特定于该类,而不是由子类更改。要做到这一点,Python允许你“神奇地”在属性中包含类的名称,这是通过在其前面添加双下划线来完成的。也就是说,如果我们使用update
而不是__update
,Python会自动将属性重命名为(类似)update
。然后,当子类覆盖_Mapping__update
时,双下划线版本将保持类本地,因此不会中断。所以我们会这样做
update
现在,即使在class Mapping:
def __init__(self, iterable):
self.__update(iterable)
def update(self, iterable):
<stuff>
__update = update # private copy for initialiser
class MappingSubclass(Mapping):
def update(self, keys, values):
<stuff>
中覆盖了update
,保存为MappingSubClass
的{{1}}的私有副本也会被修改为update
,因此代码可以正常运行应该如此。
不幸的是,这确实存在以前缀为双属性的属性名称看起来像一样但实际上是另一个的问题。那么,通常的建议是不要使用它们,除非你发现自己处于这种情况;单个下划线就足够了。
答案 1 :(得分:1)
以__
开头但 以__
结尾的属性是Python的“私有”属性。
它们在内部重命名为_CLASSNAME__ATTRNAME
,因此您实际上仍然可以通过类外的命名来访问它们,但不应该这样做。当作者希望他们是私人的时,他们肯定不是私人的,因为他想对用户嗤之以鼻。
答案 2 :(得分:0)
看起来保留了__
(双_
)前缀;将其更改为单个_
应该可以解决问题。