42

Possible Duplicate:
Making a method private in a python subclass
Private Variables and Methods in Python

How can I define a method in a python class that is protected and only subclasses can see it?

This is my code:

class BaseType(Model):
    def __init__(self):
        Model.__init__(self, self.__defaults())


    def __defaults(self):
        return {'name': {},
                'readonly': {},
                'constraints': {'value': UniqueMap()},
                'cType': {}
        }


    cType = property(lambda self: self.getAttribute("cType"), lambda self, data:              self.setAttribute('cType', data))
    name = property(lambda self: self.getAttribute("name"), lambda self, data: self.setAttribute('name', data))
    readonly = property(lambda self: self.getAttribute("readonly"),
                        lambda self, data: self.setAttribute('readonly', data))

    constraints = property(lambda self: self.getAttribute("constraints"))

    def getJsCode(self):
        pass

    def getCsCode(self):
        pass


    def generateCsCode(self, template=None, constraintMap=None, **kwargs):
        if not template:
            template = self.csTemplate

        if not constraintMap: constraintMap = {}
        atts = ""

        constraintMap.update(constraintMap)

        for element in self.getNoneEmptyAttributes():
            if not AbstractType.constraintMap.has_key(element[0].lower()):
                continue
            attTemplate = Template(AbstractType.constraintMap[element[0].lower()]['cs'])
            attValue = str(element[1]['value'])
            atts += "%s  " % attTemplate.substitute({'value': attValue})

        kwargs.update(dict(attributes=atts))

        return template.substitute(kwargs)



class  MainClass(BaseType, Model):
    def __init__(self):
        #Only Model will initialize
        Model.__init__(self, self.__defaults())
        BaseType.__init__(self)

    def __defaults(self):
        return {'name': {},
                'fields': {'value': UniqueMap()},
                'innerClass': {'value': UniqueMap()},
                'types': {}
        }

    fields = property(lambda self: self.getAttribute("fields"))
    innerClass = property(lambda self: self.getAttribute("innerClass"))
    types = property(lambda self: self.getAttribute("types"))


    @staticmethod
    def isType(iType):
    #        return type(widget) in WidgetSelector.widgets.itervalues()
        return isinstance(iType, AbstractType)

    def addType(self, type):
        if not MainClass.isType(type):
            raise Exception, "Unknown widget type %s" % type
        self.types[type.name] = type

I want that just subclasses of BaseType see the generateCsCode method of BaseType.

Community
  • 1
  • 1
Pooya
  • 4,385
  • 6
  • 45
  • 73
  • @jamylak No No no no no I just want to say how to define a method protected, I know about underscore – Pooya Jul 14 '12 at 11:44
  • Why minus??? why? it is my problem and I searched a lot and I did not find anything – Pooya Jul 14 '12 at 11:46
  • 1
    @Pooya: you have your answer: You don't do this in Python. Describe the larger problem, and we can help you find a Python-appropriate solution. – Ned Batchelder Jul 14 '12 at 11:47
  • what is the difference between just one line of my question and this amount of lines on my code? there is a lot of paranoid peoples – Pooya Jul 14 '12 at 11:55
  • @Pooya: we are not paranoid. We are trying to help you find a solution to your problem. You haven't explained why it is important to hide `generateCsCode`. Why will other code try to call it? What bad thing will happen if they do? Why aren't those developers reading your docs that say not to call it? – Ned Batchelder Jul 14 '12 at 11:58
  • @Pooya: btw, this line `constraintMap.update(constraintMap)` does nothing, you are updating a dictionary with itself. – Ned Batchelder Jul 14 '12 at 12:00
  • @NedBatchelder I'm writing a code generator from a DSL, that I've defined it, only subclasses know how to use generateCsCode correctly, I want to write a framework and I don't want other developers call this method – Pooya Jul 14 '12 at 12:02
  • 2
    @Pooya, ok, you can't do it. Write the docs explaining what developers should call and what they should not. That's the Python way. – Ned Batchelder Jul 14 '12 at 12:04
  • @NedBatchelder yes. I did not completely finish my code – Pooya Jul 14 '12 at 12:07
  • @NedBatchelder Write the docs explaining what developers should call and what they should not? I think this is very idealistic, in our company developers do not write or read docs – Pooya Jul 14 '12 at 12:11
  • 3
    If your developers don't read docs, you have a bigger problem. Fix that first. Yes, I know it is difficult, but a compiler can't improve your team. – Ned Batchelder Jul 14 '12 at 12:16

2 Answers2

103

Python does not support access protection as C++/Java/C# does. Everything is public. The motto is, "We're all adults here." Document your classes, and insist that your collaborators read and follow the documentation.

The culture in Python is that names starting with underscores mean, "don't use these unless you really know you should." You might choose to begin your "protected" methods with underscores. But keep in mind, this is just a convention, it doesn't change how the method can be accessed.

Names beginning with double underscores (__name) are mangled, so that inheritance hierarchies can be built without fear of name collisions. Some people use these for "private" methods, but again, it doesn't change how the method can be accessed.

The best strategy is to get used to a model where all the code in a single process has to be written to get along.

Ned Batchelder
  • 364,293
  • 75
  • 561
  • 662
  • 1
    yes I know about _ and __ but I want to know about how to make my method protected, exactly like protected in java – Pooya Jul 14 '12 at 11:47
  • 49
    The answer is very simple, and has been provided: You can't in Python. – Ned Batchelder Jul 14 '12 at 11:47
  • 5
    @NedBatchelder `"We are adults!"` I wish you could say that to vandals and hackers :( – John Strood Aug 02 '18 at 12:57
  • 11
    I hope the "vandals and hackers" comment isn't related to protected methods. If a hacker is running their code in your process, no amount of protected methods is going to save you. – Ned Batchelder Aug 02 '18 at 14:32
13

You can't. Python intentionally does not support access control. By convention, methods starting with an underscore are private, and you should clearly state in the documentation who is supposed to use the method.

Sven Marnach
  • 574,206
  • 118
  • 941
  • 841
  • 17
    By convention, one underscore is considered protected and two underscores are considered private. – l__flex__l Aug 17 '16 at 14:09
  • 1
    @l__flex__l: Double leading underscores for instance attributes invokes name mangling with very specific semantics. It's not a convention, it's part of the language defintion. According to PEP 8, one leading underscore is a "weak internal use indicator". I don't think there is any useful analogy to the C++ "protected" and "private" access modificators. – Sven Marnach Aug 22 '16 at 10:37
  • 3
    In the PEP 8 check out the section "Designing for inheritance". Particularly the paragraph that starts with "Another category of attributes are those that are part of the "subclass API" (often called **"protected"** in other languages)". To me, that section describes protected attributes. Also many others believe so [like this guy](http://radek.io/2011/07/21/private-protected-and-public-in-python/). I know articles on the internet is never a proof. But, enough people agree on this so that by definition is a convention, no? – l__flex__l Aug 28 '16 at 11:26
  • @l__flex__l: Fair enough. :) – Sven Marnach Aug 28 '16 at 14:27