开发者

python and static methods

开发者 https://www.devze.com 2023-03-27 15:23 出处:网络
So here is my situation. I have a class ABCAdapter. Here I have declared a bunch of methods and between them I have:

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 = adapt开发者_开发知识库er_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


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.


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.


It looks like the __ (double _) prefix is reserved; changing it to a single _ should do the trick.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号