Will python never intend to support private, protected and public?

Bengt Richter bokr at oz.net
Sun Oct 2 02:08:07 EDT 2005


On 30 Sep 2005 05:23:35 -0700, Paul Rubin <http://phr.cx@NOSPAM.invalid> wrote:

>Steven D'Aprano <steve at REMOVETHIScyber.com.au> writes:
>> > It's not easy if the base classes change after you check your code in.
>> > You shouldn't need to know about that if it happens.  Modularity, remember?
>> 
>> Yes. And if you are relying on a public method in a class, and somebody
>> dynamically modifies that public method, your code will stop working too.
>
>I'm not talking about dynamic anything.  I'm talking about a normal
>software project where there are multiple people working on the code.
>You write a class and carefully make sure that none of its private
>variables collide with superclasses in modules that it imports.  You
>check in your code and go do something else.  Then the person
>maintaining the superclasses goes and changes how they use their
>private variables.  He doesn't look at your code since his modules
>don't import yours.  But now both your code and his are broken.
>
>> perhaps that mathematical certainty is appropriate for
>> your ICBM control system or nuclear reactor, but it is a needless
>> affectation for (say) a word processor. 
>
>Why on earth would you want to unnecessarily introduce random bugs
>into a word processor or anything else?  And what happened to the
>marketing claims that Python was good for critical applications?
>Maybe I should post your disclaimer every time one of those
>discussions comes up.  "Python is ok for word processors but no good
>for anything important".  Heck, some people think word processors are
>important.

I decided to read this thread today, and I still don't know exactly
what your requirements are for "private" whatevers. No one seems to
have discussed what you could do with properties and __getattribute__
and metaclasses and decorators, yet there are many possibilities
that might satisfy some or maybe all your requirements. I probably
missed something...

Semantically, you seem to be wanting to write a class with methods
accessing a selected subset of "variables" "privately." Obviously
if the class e.g. is C, there are many ways to spell C().private_var
and C.private_var. and self.private_var etc., "self" being only
a conventional spelling for an instance ref in the method context.

What "privately" seems to mean is that within a method using
private_var, you'd still like the code to read self.private_var,
and not be translated to self.__some_kind_of_extreme_mangling_private_var
even if the mangling had vanishing collision probability, like a name
built from a secure hash GUID algorithm, right?

Also, if an outside access to an instance said inst.private_var = 123
that would be ok, and bind a public attribute of that name as usual
without interfering with the methods using the bona fide self.private_var?
Or should it be an attribute error (which would thus leak the name even
if it didn't make access possible).

I take it that a clever subclassing trick (like a post somewhere in this thread
showed) should not provide access, but how about the inspect module?
Or an expression like instance.__dict__[1] if that was the sneaky spelling
of instance.private_var? (note that integers are not allowed for instance attributes,
even via get/setattr. (BTW & OTOH, interestingly type.__setattribute__(cls, att) allows integer att)
Where do you want to draw the line?
 
I'm not trying to be provocative, just to get the requirements defined ;-)

What if you could define a class something like

    class C(object):
        # privatize factory makes callable to make the changes and clean up after itself
        __metaclass__ = privatize(method_foo='private_var1 pv2', method_bar='pv2')
        ...

and have method_foo access self.private_var1 and self.pv2 as effectively private variables,
and method_bar only self.pv2 and everything else work as usual? Would that meet your
requirements? I'm not sure I could do this with just a tricky metaclass, but I am pretty
sure if you allowed byte-code-munging decoration calls from the metaclass to mess with
method_foo and method_bar (as specified in the privatize factory call args), I could.

I think I would collect the private variable names and enumerate them to produce integer "names"
for use in accessing the values via self.__dict__[integer_name].

The byte-code munging would then translate accesses to the selected names would be translated
to use the appropriate subscript constant integer_names (which would be added to the method function
constant list as necessary) and you would have .e.g.
    LOAD_FAST                0 (self)
    LOAD_ATTR                1 (__dict__)
    LOAD_CONST               1 (1)
    BINARY_SUBSCR

in place of say
    LOAD_FAST                0 (self)
    LOAD_ATTR                1 (pv2)


i.e., _SUBSCR ops instead of _ATTR ops, and analogously for STORE_ATTR and STORE_SUBSCR,
(obviously just done to the method variable accesses specified in the privatize factory call).

Alternatively, the metaclass could create a central private value dict as a hidden cell closure
variable, and the methods could be munged to have a reference constant to that hidden dict, and
then self.priv_var code could be munged to <hidden_dict_ref_constant>[id(self), 'priv_var'].

This would still leave the access door open via something like
type(instance).__dict__['method_foo'].func_code.co_consts[1][id(instance), 'priv_var']
so, again, where do you want to draw the line. Starting and communicating with a slave debugger
in another (privilaged) process?

Alternatively, it might be possible to define (in the metaclass call) __getattribute__ for the class
so that it notices when method_foo or method_bar are being accessed to create bound methods, and then bind in
a proxy "self" instead that would have self.private_var on its own "self" and delegate public
attribute accesses to the normal self. Maybe this could get around byte-code-munging at the cost
of easier breakin than via inspect etc., and less run time efficiency. Just musing ...

But the bottom line question is, would you actually use this privacy feature?

Or maybe, what are your real requirements?
;-)

Regards,
Bengt Richter



More information about the Python-list mailing list