Reputation: 8236
So here is my situation. I have a class ABCAdapter. Here I have declared a bunch of methods and between them I have:
@staticmethod
def __prepare_param_names(attributes_list, prefix = None):
....some processing....
Now from another class, namely FlowService I do:
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...
Now this fails at the call to the static method with:
AttributeError: type object 'ABCAdapter' has no attribute '_FlowService__prepare_param_names'
Now I've not used static methods so far so what is the trick here?
Regards, Bogdan
Upvotes: 2
Views: 3304
Reputation: 16860
Attributes starting with __
but not ending with __
are Python's "private" attributes.
They become renamed internally to _CLASSNAME__ATTRNAME
, so you actually can still access them through this naming outside the class, but shouldn't be done. When the author wants them to be private, they are surely not private because he'd like to kick ass the user.
Upvotes: 1
Reputation: 123612
As you probably know, Python doesn't enforce protected/private attributes: all class attributes are globally accessible. However, there is a convention that attributes whose names start with at least one _
are an implementation detail and not part of the public API.
Double-underscored names are a slight hack used for the following use case. Suppose you have
class Mapping:
def __init__(self, iterable):
self.update(iterable)
def update(self, iterable):
<stuff>
class MappingSubclass(Mapping):
def update(self, keys, values):
<stuff>
Notice that Mapping
defines a method update
, which is called in __init__
. The subclass then redefines update
with a different signature. Since the initialiser of the subclass is inherited from Mapping
while the update
method is overridden, this will cause an error when run.
To avoid this, you want Mapping
's copy of update
to be specific to that class, and not changed by subclasses. To do this, Python lets you 'magically' include the name of the class in the attribute, which is done by prefixing it with a double underscore. That is, if we used __update
instead of update
, Python would automatically rename the attribute to (something like) _Mapping__update
. Then, when a subclass overwrote update
, the double-underscore version would remain class-local and hence not break. So we would do
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>
Now, even though update
is overwritten in MappingSubClass
, the private copy of update
saved as __update
is mangled to _Mapping__update
and hence the code works as it should.
Unfortunately, this does have the problem that attribute names prefixed with double-attributes look like one thing but are actually another. The usual advice, then, is not to use them unless you find yourself in this type of situation; a single underscore will suffice elsewhere.
Upvotes: 4
Reputation: 1026
It looks like the __
(double _
) prefix is reserved; changing it to a single _
should do the trick.
Upvotes: -3