Hi, I found the paper from Steven Miale (thesis-miale.ps, 1993) on the python ftp-server. He made some interesting extensions to the object model of python. One of this extensions makes it possible to have protected class members (methods and attributes). I understood that his extensions made their way into the official python release, but his examples don't work with my python interpreter (version 1.3 for OS/2).
It would be nice to have private methods and attributes. Is there perhaps another way to get protected members?
Stefan (sbra...@ibm.net) wrote: > Hi, > I found the paper from Steven Miale (thesis-miale.ps, 1993) on the python > ftp-server. > He made some interesting extensions to the object model of python. One of > this extensions makes it possible to have protected class members (methods > and attributes).
The 'access' keyword has been officially declared defunct.
> I understood that his extensions made their way into the official python > release, but his examples don't work with my python interpreter (version > 1.3 for OS/2).
> It would be nice to have private methods and attributes. Is there perhaps > another way to get protected members?
I posted a set of patches a few days ago (look for 'Private scopes in Python') which provides private member functions and member variables in Python.
This differs from Steven's mod in the following ways:
In Steven's version, you use the access keyword to declare access rights, wheareas in mine, the variable name is prefixed with a '.', e.g.
class Shape: def move(self): self.flag = 42 return self..doit() # calling the private member fn
def .doit(self): # private member fn self..priv_flag = 99 # private member var
In my version, private data has it's own scope, so that name clashes will not occur if a private with the same name is used in a subclass. For example:
class Square(Shape): def .doit(self): # not the same as Shape's .doit self..priv_flag = 99 # not the same as Shape's .priv_flag
These patches are experimental (i.e. unofficial) but won't adversely affect existing code.
The downside is that (so far) I have had no success evoking any interest in supporting private scopes in Python (based on the response to the patches and follow-ups).
I encourage anyone who would like to see some form of 'privacy' added to Python to post on the subject- maybe we can get some kind of debate started...
Peter Munnings wrote: > The downside is that (so far) I have had no success evoking any interest in > supporting private scopes in Python (based on the response to the patches and > follow-ups).
OK, I'll bite. I was in serious deadline mode last week to get Python 1.4b2 out, so I skimmed your patches, didn't immediately see what they did, and archived the article. However, after a few days of building sandcastles and surfing the waves, I felt more inclided to study your code, so I dug them up again.
Now, I'm impressed with their elegance.
The genius of your approach is that it is pure name mangling: ".spam" translates to "<classname>.spam", and that's it. This can all be done at compile time, and without adding new instructions to the virtual machine -- the only run-time change is to from M import *.
I see some problems with your implementation (global variables!) and there is the slight problem of giving the debugger accessw to private variables (possibly solved by giving "exec" control over contexts), but my biggest problem with it right now is the overloading of "." -- this is becoming a lexical hotspot, with its use for attribute selection, in floating point literals, for ellipses in indexing (new in 1.4b2, in support of Numerical Python), and now to indicate private names...
This probably requires more thinking, as I don't immediately see a less intrusive syntactical variant. I may just have to get used to it. (Any addition to Python's syntax will be faced with a clamoring from those -- including myself -- who prefer to keep it simple, and don't want it to turn into Perl. On the other hand, consolidation shouldn't have to mean total immobility.)
It would be nice if it could be extended for "protected" variables (only usable by subclasses). I wonder if perhaps the name mangling could be changed so that ".spam" translated to "_<classname>_spam" so that there would always be a long form to access private instance variables, without giving up the protection against accidental re-use of variable names.
Enough for now... I'm not saying that I'll hack this into 1.4b3, but it's an interesting approach.
> If you get into private and protected, may I suggest the EIffel > approcach of visiblity instead of the C++ one. The notion of Point of > View defined in EIffel allows you to specify which classes (and > subclasses) are allowed to call these members of yous class. For > instance, if two classes take part in a pattern, it's highly possible > that they will call method on each other and you would like to keep > this interface dedicated to the pattern use.
> Sure, it will make things more difficult, but if you fall into the > protected approach, you can be sure that soon, someone will ask for > friends, and the whole system information hiding system will collapse, > as in C++.
> So, how far to go ?
> As there's no universal language, may be we have to consider what is > the proper use of python and not turn it into a scary monster.
Good point! Where to stop? I say, private variables are somewhat useful (though they really just save some keystrokes); for protected and friends, well, you can do that with naming conventions.
> > ... I say, private variables are somewhat > > useful (though they really just save some keystrokes) ...
> Private variables do more than just save keystrokes. They allow me to > use someone else's class hierarchy without having to know any internal > details of the classes. They also allow the implementation of those > classes to change without having any effect on my use of them.
> How can extra keystrokes give me this protection?
If the class implementor consistently used self._ClassName_varname for private variables, neither of you would have to worry. As with any kind of protection, this isn't 100% safe, but I say it's close enough.
The posted implementation of private variables translates ".spam" into "ClassName.spam"; it could just as well translate it into _ClassName_spam without serious loss of protection.
> This is a very good idea (since it requires minimal changes to the > language definition and interpreter), but I have to wonder if the > multiple dots would make the code less readable. Perhaps some variant > of Hungarian notation?
Now there's something that *really* makes your code impenetrable (for those who aren't familiar with Hungarian notation) :-)
I agree though that this is my main gripe with the proposal as it stands -- self..spam doesn't read very nicely, but I can't think of a better way to do this.
Perhaps ``self.__spam'' would be acceptable?
For backwards compatibility reasons, private variables would start with 2 underscores but *not* end in 2 underscores -- since the __spam__ convention is already in use for names that have a special meaning to the Python virtual machine (e.g. __add__) and it's too much work to explicitly check for a specific set of names.
> I agree though that this is my main gripe with the proposal as it > stands -- self..spam doesn't read very nicely, but I can't think of a > better way to do this.
In case it makes a difference, i *like* the 'self..spam' notation. To me it looks distinctive enough to stand out, but also minimal enough to be elegant... (I'm quite fond of elipses, though, so maybe i have a perverse bias!-) I'd *certainly* vote for it in favor of the 'self.__spam' - that's too similar to references to special method names, eg 'self.__spam__'.
> Question: why does the arrow point at "2" in "1..2" but at the second > "." in "a..b"?
> "1..2" is tokenized as ['1.', '.2'] while "a..b" is tokenized as ['a', '.', > '.', 'b']. The parser is probably pointing at the rightmost extent of the > first invalid token.
In <199608060059.KAA01...@baldric.pad.otc.com.au>, Peter Munnings <Peter.Munni...@nms.otc.com.au> writes:
>> It would be nice to have private methods and attributes. Is there perhaps >> another way to get protected members?
>I posted a set of patches a few days ago (look for 'Private scopes in Python') >which provides private member functions and member variables in Python.
Peter, I missed your posting, but Greg McFarlane sent it to me. Thank you for the description of your concept. It looks fine for me. Would be nice to see it in the next Python release.
Guido wrote: > I agree though that this is my main gripe with the proposal as it > stands -- self..spam doesn't read very nicely, but I can't think of a > better way to do this.
Ken wrote: In case it makes a difference, i *like* the 'self..spam' notation. To me it looks distinctive enough to stand out, but also minimal enough to be elegant...
I don't want to puff the Perl folks up too much ;-) but there are other characters that could be used besides '.' and '_' to introduce private attributes. Just about any character that can't syntactically follow a '.' would be okay. How about something from the set ['%', '~', ':']?
> I don't want to puff the Perl folks up too much ;-) but there are other > characters that could be used besides '.' and '_' to introduce private > attributes. Just about any character that can't syntactically follow a '.' > would be okay. How about something from the set ['%', '~', ':']?
I think neither of these will work very well. ~ can't be used at all, because it can be a unary operator (at least the original proposal supported "global .spam", which means that you can write ".spam=.spam+1" -- ). self.%spam and self.:spam do raise the question "what does it mean?" and also aren't very robust in the light of a single token being omitted, e.g. self.%spam -> self%spam, x[self.:spam] -> x[self:spam].
Question: why does the arrow point at "2" in "1..2" but at the second "." in "a..b"?
"1..2" is tokenized as ['1.', '.2'] while "a..b" is tokenized as ['a', '.', '.', 'b']. The parser is probably pointing at the rightmost extent of the first invalid token.
> > I agree though that this is my main gripe with the proposal as it > > stands -- self..spam doesn't read very nicely, but I can't think of a > > better way to do this.
> In case it makes a difference, i *like* the 'self..spam' notation. To me > it looks distinctive enough to stand out, but also minimal enough to be > elegant... (I'm quite fond of elipses, though, so maybe i have a perverse > bias!-) I'd *certainly* vote for it in favor of the 'self.__spam' - > that's too similar to references to special method names, eg > 'self.__spam__'.
Well... ``self..spam'' may stand out, but could anyone guess what it meant when confronted with a few examples? I doubt it -- it looks too much like ".." is a new token (maybe meaning ellipses, though those are spelled "..." in the new extensions for numerics).
On the other hand, ``self.__spam'' also stands out, and clearly is some kind of special attribute -- what kind, the manual will tell you, but until you need to know the details, you can continue reading without feeling that there might be some great magic happening.
I thought about the similarity to __spam__, and decided that that's okay: __spam__ has a special meaning for Python (hypothetically speaking) while __spam has a special meaning for the user's class.
Steven Miale (smi...@cs.indiana.edu) wrote: > From python-list-requ...@cwi.nl Thu Aug 8 17:35 EST 1996
> In article <199608060059.KAA01...@baldric.pad.otc.com.au>, > Peter Munnings <Peter.Munni...@nms.otc.com.au> wrote: > >In Steven's version, you use the access keyword to declare access rights, > >wheareas in mine, the variable name is prefixed with a '.', e.g.
> > def .doit(self): # private member fn > > self..priv_flag = 99 # private member var
> This is a very good idea (since it requires minimal changes to the > language definition and interpreter), but I have to wonder if the > multiple dots would make the code less readable.
I wonder about this myself :-) Seriously, these user-visible aspects are probably those warranting the deepest scrutiny i.e. the actual mechanics of the patch are less important than: - what it purports to do - the changes to Python's 'interface' i.e. the syntax and semantics of the language After all, you can always fix a bug in the implementation later...but it's hard to reverse an extension to the grammar.
I think that the major options are: 1. A declarative scheme e.g. a declaration 'private a, b, c' before use within a scope. This has the advantage that there is nothing special about the variable name at all. 2. A variable naming scheme based on a grammar extension. This is easy to implement and can guarantee not to break existing code, but changes the look (and possibly the philosophy) of the language. 3. A variable naming scheme _not_ based on a grammar extension (e.g. _fred is private because of a leading '_'). This has less impact on the look of the language but a big impact on existing code.
My first preference is actually for the first option (i.e. _not_ the way my patch works)...but Python currently needs declarations only for globals (which are rare in most peoples code), so this could actually be a bigger upheaval than the second option.
> Perhaps some variant of Hungarian notation?
On my soapbox: :-)
Personally I am strongly opposed to Hungarian notation in all programming languages supporting reasonable strong dynamic or static type systems (i.e. Python, SmallTalk, C++, ANSI C, Eiffel, Modula-2, Ada, Java etc etc etc).
I think it's a great help when programming in assembler or K&R C (quite a short list, isn't it?) :-)
Microsoft are great proponents of Hungarian (surprise, surprise), however their header files are packed full of typedefs which provide no type safety in ANSI C (i.e. typedef int HWND instead of typedef struct HWND_cookie *HWND).
Hungarian is a system for programmers to do their own type checking by hand. It's not really designed for a compiler.
Peter Munnings ...anti-Hungarian activist extraordinaire
Peter Munnings <Peter.Munni...@nms.otc.com.au> wrote,
> I think that the major options are: > 1. A declarative scheme e.g. a declaration 'private a, b, c' before use > within a scope. This has the advantage that there is nothing special > about the variable name at all.
This reminds me of somthing that I have been wishing for for a long time. However, I really dont like the use of the keyword 'private' for the purpose. I would rather have something much more generic in the way of an optional variable declaration syntax. The keyword 'var' seems well suited to the task. All it says is "here comes a variable".
The idea I would like to see implemented is to provide Python with a generic variable declaration syntax. It should allow the programmer to associate arbitrary "properties" with a variable. This could include, but not be limited to, things like scoping, access, or even data type restrictions. The grammar could look somthing like this:
var_stmt: 'var' var_decl (';' var_decl)* var_decl: NAME ':' var_property (',' var_property)* var_property: NAME ('.' NAME)*
(I suppose that simply allowing a var_property to be an expression would work fine too, assuming that someone wants to think about when it gets evaluated.) By allowing such a generic declaration as this, all kinds of information could easily be passed from the source to the compiler. The list of valid properties could be extended as the need arises and, in many cases, without the need to change the language. How and for what purpose the property information gets used would be entirely up to the implementation or any extension that cares to look for it.
If such a mechanism was available, I could get rid of the ugly __members__ list used by the MESS to declare structure members. Thus
class eggs(ctype.struct): __members__ = (('a', ctype.int), ('b', ctype.double))
could become
class eggs(ctype.struct): var a : ctype.int var b : ctype.double
or even
class eggs(ctype.struct): var a : ctype.int, access.private var b : ctype.double, access.protected
-- Donald Beaudry Silicon Graphics Digital Publishing/DMS 1 Cabot Road d...@sgi.com Hudson, MA 01749 ...So much code, so little time...
In article <199608090002.KAA00...@baldric.pad.otc.com.au>, Peter Munnings
<Peter.Munni...@nms.otc.com.au> wrote: > I think that the major options are: > 1. A declarative scheme e.g. a declaration 'private a, b, c' before use > within a scope. This has the advantage that there is nothing special > about the variable name at all.
But it has the disadvantage that when I'm looking at code I can't easily tell what is private and what isn't. Instead of jumping out at me right there where I'm looking I have to, for each variable, check "up above" somewhere to see if it has been declared private. For this reason I dislike data declarations in general.
> 2. A variable naming scheme based on a grammar extension. This is easy to > implement and can guarantee not to break existing code, but changes the > look (and possibly the philosophy) of the language. > 3. A variable naming scheme _not_ based on a grammar extension (e.g. _fred > is private because of a leading '_'). This has less impact on the look of > the language but a big impact on existing code.
Right. For instance I've started using two leading underscores as a personal convention meaning private to *this* class while I use one leading underscore to mean the attribute is only intended to be private to the module. Which brings up the question also of what exactly does "private" mean? I've found the class/module distinction to be valuable - I wonder if there are other useful variations(?)
Always keep in mind that everything on c.l.py is archived on dejanews; you can quickly locate expired articles like this via the Search page on www.python.org.
Guido van Rossum wrote: > I agree though that this is my main gripe with the proposal as it > stands -- self..spam doesn't read very nicely, but I can't think of a > better way to do this.
> Perhaps ``self.__spam'' would be acceptable?
personally, my vote is for the "self..spam"..
maybe i need to dig back through the Docs again, but what do the _spam variables mean? (single leading underscore).. i've seen them used in a few modules, but didn't understand their meaning any more than i first understood the __spam__() ones either. self._spam has a nice 'feel' to it, self.__spam comes dangerously close to the __spam__ thing, plus to me is aesthetically displeasing.
CM> Right. For instance I've started using two leading CM> underscores as a personal convention meaning private to *this* CM> class while I use one leading underscore to mean the attribute CM> is only intended to be private to the module. Which brings up CM> the question also of what exactly does "private" mean? I've CM> found the class/module distinction to be valuable - I wonder CM> if there are other useful variations(?)
Very interesting. I've long used a single leading underscore in my Python code to denote `privateness' of a name (and long before that, a different character in my C++ code served the same function, but for a different reason). I liked the double leading underscore proposal as soon as I saw it; I agree with Guido that __spam makes me think it's special (to user code) in a complimentary way that __spam__ makes me think it's special (to the `system'). With out the eye-parsing confusion that double dots introduce. I've now started using to double leading underscores in anticipation... :-)
The question of `private to what' hasn't come up for me. I never found much value in distinguishing between private-to-the-class and private-to-the-module, maybe because module-private names are already segregated into their own namespace. If you could inherit modules, or if from...import weren't (rightly) discouraged as much as it is, it might be a bigger problem. So I personally used the same convention when naming module-private and class-private variables, and haven't ever been confused.
To recap: my vote would be for __spam as private variables. I like this much better than any other weird character, and definitely much better than double dots.
> On the other hand, I expect that you want 'var' to apply to an > entire module, or at least to an entire class (so you need to > declare your privates only once, at the top of the class).
Pretty much... For each of module, class, and function, I would like to have access to a list (order is important) of variable names and their associated properties. From there, I (the extension writer) could make use of the information.
> This makes the required searching much harder, since the top of the > class is generally much farther back than the top of the function.
Yes, searching is much harder, but I don't really like the alternatives either. What we are talking about here is a mechanism for "tagging" variables with some extra information. A couple of methods have been proposed to solve a specific form of the problem. Now, assuming that there is a problem (arguing that there isn't should be the easiest way to shoot down this proposal), I would much prefer a generic declaration syntax that is extensible to many different problems where "tagging" is needed. Playing with the variable name (the other alternative) is just not as useful. Clearly it can't be used to pass type hints to an efficient code generator.
Of course, it's possible that I'm overestimating the number of problems that could easily be solved by tagging variables. After all, I am just a bit biased here ;)
-- Donald Beaudry Silicon Graphics Digital Publishing/DMS 1 Cabot Road d...@sgi.com Hudson, MA 01749 ...So much code, so little time...
> Right. For instance I've started using two leading underscores as a > personal convention meaning private to *this* class while I use one leading > underscore to mean the attribute is only intended to be private to the > module. Which brings up the question also of what exactly does "private" > mean? I've found the class/module distinction to be valuable - I wonder if > there are other useful variations(?)
Yes. There's already a tiny bit of support for using leading underscore to mean module-private: "from M import *" won't import such variables (you can still get at them with "from M import _spam" or by using "M._spam"). Your use of double leading underscore to mean class-private is exactly what I'd hoped to convey with my proposal.
(I also agree with Conrad's objection against variables -- sorry, Don!)
>>>>> "jPS" == jeffrey P Shell <j...@cynapses.com> writes:
jPS> maybe i need to dig back through the Docs again, but what do jPS> the _spam variables mean? (single leading underscore)..
_spam has no special meaning. I've personally used it as a convention for `private' because I like the visual separation. I think in Bastion.py there is a default that names beginning with underscore (any number of 'em) are not exported into the bastion.
> Of course, it's possible that I'm overestimating the number of > problems that could easily be solved by tagging variables. After all, > I am just a bit biased here ;)
Actually, you're probably underestimating -- which is why such a proposal should not be taken lightly. I have other plans for Python 2.0, so unless a working group (SIG?) gets formed that creates a solid proposal, based on a clear set of requirements, I'm not going to spend time on this.
Sounds like Don might volunteer to run such a SIG?