"Protected" property in Python?

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Jules Dubois

    "Protected" property in Python?

    I'm want to create a superclass with nothing but attributes and properties.
    Some of the subclasses will do nothing but provide values for the
    attributes.

    (I'd also like to make sure (1) that the subclass provides actual values
    for the attributes and (2) that no "client" module adds or removes
    attributes or properties, but I don't know how to do those.)

    I don't understand what I'm doing wrong, or maybe what I want to do is
    impossible. Here's a stripped down version of the code:

    ----------------------------------------------------------------
    #! /usr/bin/python
    class SuperClass(obje ct):
    def __init__(self):
    self.__statusCo de = "value bound in SUPERCLASS"
    getStatusCode = property(lambda self: self.__statusCo de)

    class SubClass(SuperC lass):
    def __init__(self):
    # SuperClass.__in it__(self)
    self.__statusCo de = "value bound in SUBCLASS"

    if __name__ == "__main__":
    s = SubClass()
    print s.getStatusCode
    ----------------------------------------------------------------

    If I run this program, I get an exception (output wrapped by hand):

    Traceback (most recent call last):
    File "./xxx.py", line 14, in ?
    print s.getStatusCode
    File "./xxx.py", line 5, in <lambda>
    getStatusCode = property(lambda self: self.__statusCo de)
    AttributeError: 'SubClass' object has no attribute \
    '_SuperClass__s tatusCode'

    Why is the lambda function attempting to access the superclass' attribute
    and not the subclass' attribute? Can I make it not do that?

    If I replace "__statusCo de" with "_statusCod e", the output is

    value bound in SUBCLASS

    as I want. However, "_statusCod e" is then visible from the outside, as I
    don't want.

    Am I missing something about how Python works?

    Is my problem more fundamental, like not understanding OO programming?

    I'm able to RTFM if someone would provide a pointer.
  • Sean Ross

    #2
    Re: &quot;Protected &quot; property in Python?


    "Jules Dubois" <bogus@invalid. tld> wrote in message
    news:1rgll5psln cci.1iu0qs9ekf4 5q.dlg@40tude.n et...
    [snip][color=blue]
    > Why is the lambda function attempting to access the superclass' attribute
    > and not the subclass' attribute? Can I make it not do that?
    >[/color]

    Try this:

    getStatusCode = property(lambda self: getattr(self,
    '_%s__statusCod e'%self.__class __.__name__))

    HTH
    Sean



    Comment

    • Alex Martelli

      #3
      Re: &quot;Protected &quot; property in Python?

      Jules Dubois wrote:
      [color=blue]
      > I'm want to create a superclass with nothing but attributes and
      > properties. Some of the subclasses will do nothing but provide values for
      > the attributes.
      >
      > (I'd also like to make sure (1) that the subclass provides actual values
      > for the attributes and (2) that no "client" module adds or removes
      > attributes or properties, but I don't know how to do those.)[/color]

      You'll need a custom metaclass; you need to read up on this concept,
      but these days you can find explanations on the net. Any class is an
      instance of a metaclass -- the class statement implies a call to the
      metaclass, which in turn means the MC's __new__ then __init__ as
      in any other class-call (instantiation) -- and that call must provide and
      initialize the class object.

      Not sure what you mean by "client" module, but in general Python is
      not about stopping Python programers from performing tasks -- so if
      you see your task as one of placing inhibitions on other Pythonistas
      who want to use your code, you're in for a fight. Still, you can do a good
      job of ensuring that things don't happen _accidentally_, and that is
      generally good enough -- a "malicious" other programmer is quite a
      different kettle of fish, though.


      Anyway, your problem has nothing to do with these difficult issues
      (it's more of an issue of running before one can walk):
      [color=blue]
      > I don't understand what I'm doing wrong, or maybe what I want to do is
      > impossible. Here's a stripped down version of the code:
      >
      > ----------------------------------------------------------------
      > #! /usr/bin/python
      > class SuperClass(obje ct):
      > def __init__(self):
      > self.__statusCo de = "value bound in SUPERCLASS"
      > getStatusCode = property(lambda self: self.__statusCo de)[/color]

      This mangles the identifier __statusCode within class SuperClass,
      giving _SuperClass__st atusCode.
      [color=blue]
      > class SubClass(SuperC lass):
      > def __init__(self):
      > # SuperClass.__in it__(self)
      > self.__statusCo de = "value bound in SUBCLASS"[/color]

      But this mangles it within class SubClass, giving _SubClass__stat usCode, a
      different identifier. That's what leading __ is all about: giving an
      identifier that strictly depends on the class where it's LEXICALLY found.
      If you don't want that, don't use two leading underscores: use just one
      (advisory indicator of privacy) and be happy. Or, you *CAN* simulate by
      hand the mangling, though there's little point in so doing -- e.g., in
      SuperClass, you can code:

      def getStatusCode(s elf):
      attr_name = '_%s__statusCod e' % self.__class__. __name__
      return getattr(self, attr_name)
      statusCode = property(getSta tusCode)

      note that the leading get normally denotes an accessor method -- the
      point of properties is having something that doesn't LOOK like a getter,
      so naming one with a leading 'get' is quite peculiar.
      [color=blue]
      > Why is the lambda function attempting to access the superclass' attribute
      > and not the subclass' attribute? Can I make it not do that?[/color]

      Sure.
      [color=blue]
      > If I replace "__statusCo de" with "_statusCod e", the output is
      >
      > value bound in SUBCLASS
      >
      > as I want. However, "_statusCod e" is then visible from the outside, as I
      > don't want.[/color]

      There is no way to make the value NOT "visible from the outside" -- WITH
      the leading underscores, it's STILL visible, as "_SubClass__sta tusCode",
      anyway. If you stashed the value away in a remote dict and encoded it
      with strong cryptography, it would STILL be visible -- nothing stops a
      halfway determined attacker from duplicating whatever way your superclass
      uses to get at it. Treating "client code programmers" as enemies and your
      task as one of fighting against them to stop them from "abusing" your
      pristine design is not Python's strength -- indeed the tools you used to
      have for this fight, rexec and Bastion, were recently removed as they did
      not prove strong enough for this thankless task. In Python, you had better
      think of all these mechanisms as ADVISORY "security" -- and then the
      simple convention of the one leading underscore should be ample: anybody
      who deliberately uses an identifier starting with a leading underscore is
      knowingly going beyond the interface to the implementation, anyway. The
      TWO leading underscores serve the specific purpose of allowing programmers
      who code subclasses to blissfully ignore whatever private implementation
      names the superclass has used for attributes, as it ensures against any
      accidental name clashes -- using them for *communication* between base
      and derived classes is weird, since they're mainly for *isolating* base from
      derived classes.

      [color=blue]
      > Am I missing something about how Python works?
      >
      > Is my problem more fundamental, like not understanding OO programming?
      >
      > I'm able to RTFM if someone would provide a pointer.[/color]

      Googling for:
      Python metaclass
      gives you plenty of material to chew on. I also suggest my presentation on
      the subject, PDF slides at http://www.strakt.com/docs/ep03_meta.pdf .


      Alex

      Comment

      • Camilo Olarte

        #4
        Re: &quot;Protected &quot; property in Python?

        On Mon, 22 Sep 2003 23:22:44 -0600
        Jules Dubois <bogus@invalid. tld> wrote:
        [color=blue]
        > I'm want to create a superclass with nothing but attributes and properties.
        > Some of the subclasses will do nothing but provide values for the
        > attributes.
        > (I'd also like to make sure (1) that the subclass provides actual values
        > for the attributes and (2) that no "client" module adds or removes
        > attributes or properties, but I don't know how to do those.)
        > I don't understand what I'm doing wrong, or maybe what I want to do is
        > impossible. Here's a stripped down version of the code:[/color]

        Question : why didn't you initialize your super class????
        if you do it passing the values you want as arguments then you could have a code
        like :
        <PYTHON>
        #! /usr/bin/python
        class SuperClass(obje ct):
        def __init__(self,s tat_code):
        # self.__statusCo de = "value bound in SUPERCLASS"
        self.__statusCo de = stat_code
        getStatusCode = property(lambda self: self.__statusCo de)
        class SubClass(SuperC lass):
        def __init__(self):
        self.__statusCo de = "value bound in SUBCLASS"
        SuperClass.__in it__(self,self. __statusCode )
        if __name__ == "__main__":
        s = SubClass()
        print s.getStatusCode
        print
        try :
        print s.__statusCode
        except :
        print "cannot do that.. print s.__statusCode"
        </PYTHON>

        where you don't have private attributes visible and yet you have the values you
        passed from the subclass..

        NOTE : later on accessing those values from your sublass other than from the SuperClass initialization is other story...(setatt ribute,getattri bute...or self.functions)
        In your local python documentation.. read the tutorial section on classes:
        /python2.2-doc/html/tut/node11.htm

        Comment

        Working...