"Protected" property in Python?

Discussion in 'Python' started by Jules Dubois, Sep 23, 2003.

  1. Jules Dubois

    Jules Dubois Guest

    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(object):
    def __init__(self):
    self.__statusCode = "value bound in SUPERCLASS"
    getStatusCode = property(lambda self: self.__statusCode)

    class SubClass(SuperClass):
    def __init__(self):
    # SuperClass.__init__(self)
    self.__statusCode = "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.__statusCode)
    AttributeError: 'SubClass' object has no attribute \
    '_SuperClass__statusCode'

    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 "__statusCode" with "_statusCode", the output is

    value bound in SUBCLASS

    as I want. However, "_statusCode" 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.
    Jules Dubois, Sep 23, 2003
    #1
    1. Advertising

  2. Jules Dubois

    Sean Ross Guest

    "Jules Dubois" <> wrote in message
    news:...
    [snip]
    > Why is the lambda function attempting to access the superclass' attribute
    > and not the subclass' attribute? Can I make it not do that?
    >


    Try this:

    getStatusCode = property(lambda self: getattr(self,
    '_%s__statusCode'%self.__class__.__name__))

    HTH
    Sean
    Sean Ross, Sep 23, 2003
    #2
    1. Advertising

  3. Jules Dubois wrote:

    > 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.)


    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):

    > 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(object):
    > def __init__(self):
    > self.__statusCode = "value bound in SUPERCLASS"
    > getStatusCode = property(lambda self: self.__statusCode)


    This mangles the identifier __statusCode within class SuperClass,
    giving _SuperClass__statusCode.

    > class SubClass(SuperClass):
    > def __init__(self):
    > # SuperClass.__init__(self)
    > self.__statusCode = "value bound in SUBCLASS"


    But this mangles it within class SubClass, giving _SubClass__statusCode, 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(self):
    attr_name = '_%s__statusCode' % self.__class__.__name__
    return getattr(self, attr_name)
    statusCode = property(getStatusCode)

    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.

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


    Sure.

    > If I replace "__statusCode" with "_statusCode", the output is
    >
    > value bound in SUBCLASS
    >
    > as I want. However, "_statusCode" is then visible from the outside, as I
    > don't want.


    There is no way to make the value NOT "visible from the outside" -- WITH
    the leading underscores, it's STILL visible, as "_SubClass__statusCode",
    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.


    > 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.


    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
    Alex Martelli, Sep 23, 2003
    #3
  4. On Mon, 22 Sep 2003 23:22:44 -0600
    Jules Dubois <> wrote:

    > 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:


    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(object):
    def __init__(self,stat_code):
    # self.__statusCode = "value bound in SUPERCLASS"
    self.__statusCode = stat_code
    getStatusCode = property(lambda self: self.__statusCode)
    class SubClass(SuperClass):
    def __init__(self):
    self.__statusCode = "value bound in SUBCLASS"
    SuperClass.__init__(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...(setattribute,getattribute...or self.functions)
    In your local python documentation.. read the tutorial section on classes:
    /python2.2-doc/html/tut/node11.htm
    Camilo Olarte, Sep 23, 2003
    #4
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Andreas Klemt
    Replies:
    2
    Views:
    551
    Andreas Klemt
    Jul 5, 2003
  2. Steve Holden
    Replies:
    2
    Views:
    316
    Alex Martelli
    Oct 8, 2005
  3. Simon Brunning
    Replies:
    10
    Views:
    487
    Alex Martelli
    Oct 8, 2005
  4. Tony Meyer
    Replies:
    2
    Views:
    374
    Tony Meyer
    Sep 28, 2005
  5. Ingvar Nilsen
    Replies:
    0
    Views:
    427
    Ingvar Nilsen
    Dec 16, 2004
Loading...

Share This Page