> I just posted to my blog about a feature that I'd like to see added to > Python. Before I go through the trouble of learning how to write a PEP or > how to extend the Python interpreter, I want to know what people in the > community have to say about it.
> As far as I know, a feature like this does not appear in any existing PEPs. > (If it does I would appreciate it if someone could tell me what PEP it is.)
> Please give and comments you may have, but I request that you be > constructive if you must criticize...thank you!
En Wed, 25 Nov 2009 23:35:06 -0300, The Music Guy <FearsomeDragon...@gmail.com> escribi :
> I just posted to my blog about a feature that I'd like to see added to > Python. Before I go through the trouble of learning how to write a PEP or > how to extend the Python interpreter, I want to know what people in the > community have to say about it.
> As far as I know, a feature like this does not appear in any existing > PEPs. > (If it does I would appreciate it if someone could tell me what PEP it > is.)
Brad wrote: > On Nov 25, 10:49 pm, Chris Rebert <c...@rebertia.com> wrote: >> On Wed, Nov 25, 2009 at 6:35 PM, The Music Guy
>> <FearsomeDragon...@gmail.com> wrote: >>> Hello all, >>> I just posted to my blog about a feature that I'd like to see added to >>> Python. Before I go through the trouble of learning how to write a PEP or >>> how to extend the Python interpreter, I want to know what people in the >>> community have to say about it. >>> http://alphaios.blogspot.com/2009/11/python-string-inferred-names-wor... >>> As far as I know, a feature like this does not appear in any existing PEPs. >>> (If it does I would appreciate it if someone could tell me what PEP it is.) >>> Please give and comments you may have, but I request that you be >>> constructive if you must criticize...thank you! >> Ugly, Perlish, and as you even admit, entirely unnecessary. >> And you'd need to wait at least a year anyway:http://www.python.org/dev/peps/pep-3003/
> Like I said, lots of things in Python are "unnecessary," but that > doesn't make them "useless," and it certainly doesn't mean they > shouldn't exist. My proposed feature is not useless; I think it would > make a lot of code easier.
How is it easier than using dictionary with string as keys? setattr, getattr, and delattr are already sugar for accessing instance.__dict__.
You make a comparison with decorators; even if it's unnecessary it does eliminate a DRY case (don't repeat yourself): def foo(self): pass foo = property(foo)
there you repeat foo three times unnecessarily, instead of: @property def foo(self): pass
people already bashed decorator syntax because it is ungoogleable; a non-python programmer reading a python code can't google "python @" to find out that it's a decorator. $ has very similar problem; and we don't want to add more of this wart.
You also make with iterators and generators. Iterator and generator is an implication of the core design of python; because python chose not to have a for-loop (python's "for-loop" is actually a for-each-loop). Without the iterator protocol, it is not possible to make an iterable class and people would have to use "for x in range(len(foo)):" every so often. Iterator protocol also makes it possible to have infinite iterable (e.g. for x in primegenerator(): produces prime numbers indefinitely).
A list comprehension is space saver; it saves a lot of lines for the very common operation:
a = [] for x in orig: if test(x): a.append(transform(x))
into one concise line: a = [transform(x) for x in orig if test(x)]
Also a generator comprehension can be passed around without being evaluated.
As you see, these "unnecessary features" does have significant benefits to it. Decorators reduced DRY, iterators/generators eliminates the need of range-len for-loop, list comprehension is huge space saver.
The proposed syntax only saves a few character, does not eliminate any DRY, is ungoogleable, and looks confusing to me. Is there any significant benefit from it?
I don't think getattr and setattr are used anywhere near frequently enough to justify special syntax.
To warrant having its own synax, a feature needs to be used *all the time*. If you find yourself using getattr and setattr that much, it's probably a symptom that you're abusing namespaces for things that would be better done using dictionaries.
(A frequent question asked by newcomers from certain other kinds of languages is something like "How do I assign to a variable whose name is in another variable?" The answer is almost always "Don't do that, use a dictionary.")
Gregory Ewing wrote: >> On Wed, 25 Nov 2009 20:44:36 -0600, The Music Guy >> <music...@alphaios.net> declaimed the following in >> gmane.comp.python.general:
>>> I just posted to my blog about a feature that I'd like to see added to >>> Python.
> To warrant having its own synax, a feature needs to be > used *all the time*. If you find yourself using getattr > and setattr that much, it's probably a symptom that > you're abusing namespaces for things that would be > better done using dictionaries.
> (A frequent question asked by newcomers from certain > other kinds of languages is something like "How do I > assign to a variable whose name is in another variable?" > The answer is almost always "Don't do that, use a > dictionary.")
> En Wed, 25 Nov 2009 23:35:06 -0300, The Music Guy > <FearsomeDragon...@gmail.com> escribió:
> > I just posted to my blog about a feature that I'd like to see added to > > Python. Before I go through the trouble of learning how to write a PEP or > > how to extend the Python interpreter, I want to know what people in the > > community have to say about it.
> > As far as I know, a feature like this does not appear in any existing > > PEPs. > > (If it does I would appreciate it if someone could tell me what PEP it > > is.)
That aside, I still feel that a new syntax would be a better solution than a new class. And, anyway, what I'm proposing isn't *quite* the same as what Ben North proposed. Ben's idea was *strictly* to create shorthand syntax to the getattr/setattr/delattr in the context of specific objects. What I'm suggesting could be more accurately described as a namespace-neutral transformation of the value of an expression into a name. So if "bar" is the value of foo, then when the interpreter sees $foo, it reads bar. And when the interpreter sees obj.$foo, it reads obj.bar. It can effectively be used in the same way as Ben's proposal, but also for names in the current scope.
Next thing is, I can't see logically how the path of the discussion of the proposal lead to the proposal being rejected. It looked like a lot of people really liked the idea--including Guido himself--and several examples were given about how it could be useful. The final verdict on the matter just doesn't make logical sense in the context of the discussions.
The main problem that people had with it was more to do with the syntactical form than with the feature itself, but that's easily adjusted. Not to sound pompous (ahem), but the syntax that I propose does not suffer from the problems that people had with other suggestions, i.e. it looks less like a typo (how often do you accidentally type a "$" when you meant to type a "(" or a "." ?), it does not get easily confused as a function call, or indexing syntax, or an ordinary member lookup, because none of those things rely on the $ as an operator. Nothing does.
As for it not being useful enough to justify new syntax, well, I think Ben showed pretty well that it actually is. Approximately 600 uses of the get*r functions were used in the Python 2.5 standard library alone. Now 2.7 is around the corner and that number has probably grown, if only a little bit. Besides that, as I already stated in the blog, a feature like this would make metaclassing code that generates properties and methods much easier to write and understand.
Nonetheless, the fact remains that the feature I'm proposing closely resembles one that has already been rejected... Well, it's been a few years since then. Maybe its about time for another PEP to be proposed?
On Nov 27, 10:43 am, The Music Guy <music...@alphaios.net> wrote: [snip]
> Nonetheless, the fact remains that the feature I'm proposing closely > resembles one that has already been rejected... Well, it's been a few > years since then. Maybe its about time for another PEP to be proposed?
Judging by the response you've got from about half-a-dozen sensible people, I say maybe it's NOT about time.
> Nonetheless, the fact remains that the feature I'm proposing closely > resembles one that has already been rejected... Well, it's been a few > years since then.
The passage of time is insufficient. The idea also needs to have greater merit now than before. You haven't demonstrated that it does.
> Maybe its about time for another PEP to be proposed?
Before that happens, you might like to know that Guido (like many others) far prefers to communicate with people who use their real name, as one might use to introduce oneself face-to-face.
-- \ “I call him Governor Bush because that's the only political | `\ office he's ever held legally.” —George Carlin, 2008 | _o__) | Ben Finney
On 25Nov2009 21:45, Brad <themusicguy...@gmail.com> wrote: | On Nov 25, 10:49 pm, Chris Rebert <c...@rebertia.com> wrote: | > On Wed, Nov 25, 2009 at 6:35 PM, The Music Guy
| > > I just posted to my blog about a feature that I'd like to see added to | > > Python. Before I go through the trouble of learning how to write a PEP or | > > how to extend the Python interpreter, I want to know what people in the | > > community have to say about it. | > >http://alphaios.blogspot.com/2009/11/python-string-inferred-names-wor... [...] | > Ugly, Perlish, and as you even admit, entirely unnecessary. | > And you'd need to wait at least a year anyway:http://www.python.org/dev/peps/pep-3003/ | | Like I said, lots of things in Python are "unnecessary," but that | doesn't make them "useless," and it certainly doesn't mean they | shouldn't exist. My proposed feature is not useless; I think it would | make a lot of code easier.
The Zen promotes the guideline that there should be only one (obvious) way to do most things and that's a surprisingly effective design rule.
For your idea the obvious ways already exist.
If you really want this you can achieve nearly the same conciseness by defining __setitem__ and __getitem__ so that:
For reading rec.moto, I use one of those carbon-fiber Logitech mice w/a little 'No Fear' sticker on it. - Mike Hardcore DoD#5010 <mo...@netcom.com> Apologies to Primus
Cameron Simpson <c...@zip.com.au> writes: > The Zen promotes the guideline that there should be only one (obvious) > way to do most things and that's a surprisingly effective design rule.
It's also important to realise that the Zen places the “preferably only one” in a parenthetical, and note that “preferably” qualifier. That is, it's:
There should be one obvious way to do it.
without that parenthetical. I think that “obvious” is the important part there, and seems to be to be the design principle that (far more than “only one”) is guiding in Python's development.
-- \ “Too many pieces of music finish too long after the end.” —Igor | `\ Stravinskey | _o__) | Ben Finney
The Music Guy wrote: > As for it not being useful enough to justify new syntax, well, I think > Ben showed pretty well that it actually is. Approximately 600 uses of > the get*r functions were used in the Python 2.5 standard library > alone.
The standard library isn't necessarily representative of Python code in general. I just looked at three of my projects, and out of a total of 45954 lines (about half the size of the stdlib) I found only 37 uses of getattr and setattr.
Also, many of the uses of getattr in the std lib appear to be of the 3-argument form, which your suggested syntax doesn't cover. If I exclude those from my code, I'm left with only 18 uses.
So I would only be able to use your syntax in about 0.04% of the lines of code that I typically write.
En Thu, 26 Nov 2009 20:43:04 -0300, The Music Guy <music...@alphaios.net> escribi :
> Nonetheless, the fact remains that the feature I'm proposing closely > resembles one that has already been rejected... Well, it's been a few > years since then. Maybe its about time for another PEP to be proposed?
You'll have to wait a few more years; in case you missed the previous reference to PEP 3003 up in the thread, the language syntax is frozen by now [1]
On Nov 26, 9:10 pm, "Gabriel Genellina" <gagsl-...@yahoo.com.ar> wrote:
> En Thu, 26 Nov 2009 20:43:04 -0300, The Music Guy <music...@alphaios.net> > escribió:
> > Nonetheless, the fact remains that the feature I'm proposing closely > > resembles one that has already been rejected... Well, it's been a few > > years since then. Maybe its about time for another PEP to be proposed?
> You'll have to wait a few more years; in case you missed the previous > reference to PEP 3003 up in the thread, the language syntax is frozen by > now [1]
That PEP seems to pretty clearly state that it applies only to the 3.x branch and not to the 2.x branch. Is there maybe a slim chance of getting my idea added to 2.7, or even 2.8? :D
On Nov 26, 7:49 pm, Gregory Ewing <greg.ew...@canterbury.ac.nz> wrote:
> [...] Also, many of the uses of getattr in the std lib appear > to be of the 3-argument form, which your suggested syntax > doesn't cover. [...]
Good point. After excluding those, only ~435 uses would work for my proposed syntax. Still seems fairly significant to me, though.
Also, please keep in mind that I never suggested that the get*r functions should be removed from the language precisely because they DO work in ways that my proposed syntax does not, and that removing them would make a lot of existing code fail. For the purpose of the 3- argument form, I would still prefer using getattr or even a defaultdict depending on the task. (For the record, I disagree with the 2-argument form of Ben's proposed syntax; that's confusing and hard to read.)
As for your code, I haven't seen it, so it would be hard for me to say exactly how the new syntax would come into play. What I can tell you, however, is that the parts of your code that would use it would probably be easier to read and change to anyone with a firm grasp of the proposed syntax.
Quantity of code is definitely important, but I don't want to underwrite the importance of quality, either. Even if only 30 lines of code--rounding down--out of 40,000 would use it, those 40 lines would probably be easier to read and understand. (Off-handedly, you might also find that the availability of the new syntax makes new solutions to some task obvious which previously were not, so the number could rise.)
The discussion of PEP 363 presented some good examples of what I'm talking about. Consider this code, which is a paraphrase of code that appeared in the discussion:
Even if this sort of thing only needed to happen a few times in an entire project, the project as a whole could only benefit from it. My projects rely on a lot of metaclassing for the automatic generation of properties and methods, which saves tremendous amounts of coding. However, the code for the metaclasses is confusing because it relies heavily on the getattr and setattr functions for accessing not only the classes being created but also the instances of those classes. The code for the metaclasses themselves only constitute a small percentage of the overall code for the projects, but that doesn't mean the code doesn't need to be easy to read and understand. Dynamic attribute access via a syntactical construct would be very beneficial for me.
Back to PEP 3003, I understand the odds of getting the feature in right now are slim. I get it. But that doesn't mean the idea of the feature is a bad one. There are other things that can be done in the mean time until the moratorium is lifted, like perfecting the syntax and implementation details, or whatever.
> As for your code, I haven't seen it, so it would be hard for me to say > exactly how the new syntax would come into play. What I can tell you, > however, is that the parts of your code that would use it would > probably be easier to read and change to anyone with a firm grasp of > the proposed syntax.
Isn't this much easier to read and grasp?
obj.d["my_%s" % foo] += 3
doesn't need new syntax as well.
> Even if this sort of thing only needed to happen a few times in an > entire project, the project as a whole could only benefit from it. My > projects rely on a lot of metaclassing for the automatic generation of > properties and methods, which saves tremendous amounts of coding.
If you use it a lot, it is likely 1) you have abused class syntax for what should have been a dict or 2) what you need is to override __getattr__/__getattribute__ and __setattr__
On Fri, 27 Nov 2009 20:02:31 -0800, The Music Guy wrote: > That PEP seems to pretty clearly state that it applies only to the 3.x > branch and not to the 2.x branch. Is there maybe a slim chance of > getting my idea added to 2.7, or even 2.8? :D
The only new features being added to 2.7 are features which are also being added to 3.x. There is no chance at all of having new features added to 2.7 which isn't added to 3, unless that feature is specifically to make it easier to migrate from 2 to 3.
On Nov 28, 3:07 am, Lie Ryan <lie.1...@gmail.com> wrote:
> On 11/28/2009 3:08 PM, The Music Guy wrote:
> > As for your code, I haven't seen it, so it would be hard for me to say > > exactly how the new syntax would come into play. What I can tell you, > > however, is that the parts of your code that would use it would > > probably be easier to read and change to anyone with a firm grasp of > > the proposed syntax.
> Isn't this much easier to read and grasp?
> obj.d["my_%s" % foo] += 3
> doesn't need new syntax as well.
Actually, that's similar to my backup solution, which is a variant of the "attrs" class that PEP 363 provides. It does make things easier to read, but a new syntax would still be better because:
1.) A new syntax would apply to _everything_ as it would be a hook to the very mechanism that gets the value of a member from an object and does not rely on an object defining the magic "d" property. I suppose you could argue that an enhancement could be made to the language that says that all objects must define the magic "d" (so the builins "object" and "type" would have to define it). That also has the added benefit of not conflicting with PEP 3003, which says it is fine to add new methods (and I would assume properties as well) to existing classes.
2.) Ben's patch for his proposed syntax generated an aproximate 1% performance hit for the interpreter overall versus a >40% increase where code that used the getattr/settattr functions was modified to use the proposed syntax. The magic "d" MIGHT have a performance increase over the getattr/setattr functions, but a syntax would still be significantly faster because there would be less function dereferencing/calling. For the purposes that I had intended for the syntax to be used, that would definitely matter.
> If you use it a lot, it is likely 1) you have abused class syntax for > what should have been a dict or 2) what you need is to override > __getattr__/__getattribute__ and __setattr__
Oh boy...here we go. :|
Please listen. In all the time I've spent in the coding community (that's at least 7 years) and especially since I started paying attention to the Python community (2 years), I have noticed a trend: When one coder does something that another cannot understand, frequently the other will assume the former is not only doing things wrong, but is doing them _blatantly_ wrong. I have caught myself making that very assumption many times in the past, and I've tried hard to build up an immunity against the impulse to make that assumption. At this point, I don't even believe in such a thing as a universal "wrong way" and a "right way" to code that applies to every circumstance. The way to solve a problem depends on the problem. When it comes to coding, there is not an absolute "right" way or "wrong" way--unless we're talking about, say, stealing closed source code without permission, or deliberately coding in a way that will cause problems for the end user (like causing memory clogs or buffer overflows and whatnot).
All of this can be determined through common sense. And yet I continue to see the attitude of "my solution is the ONLY solution to your problem, and it doesn't matter if I don't even actually understand the problem." Not everyone does this, but it is a frequent enough occurence to be worth noting. If I had to pull a number out of my magic bag, I would say 4 out of 10 resposes have at least a hint of this attitude, and 2.5/10 where it is very obvious.
But I digress. I've already gone over other possible solutions and the one I am using seems to fit the bill better than any other yet presented to me, including the ones you just suggested. In fact, I'm fairly certain that __getattr__ and friends even apply to the situation, or if they do, they're certainly inferior alternatives to the use of getattr/setattr. Not that I'm calling you inferior--I'm just saying that if you had a better understanding of the problem you would not see __getatrr__ et al. as parts of a possible solution because they don't really make logical sense given the circumstances.
...and I have one last thing to say. I feel very strongly that metaclassing is a fiercely underestimated and largely untapped source of good coding solutions. I hope that many coders will see this and help to make it more adoptable by the masses; at present it is seen as a big, scary beast that is hard to tame and even harder to drive. It is portrayed as something dangerous that should only be used in relatively rare situations. I disagree with this view. It is the view itself which makes it seem so dangerous (in other words, it is self- perpetuating).
Well, that's about enough yakking for 5:30 in the morning...time to give my noggin a rest.
The Music Guy <fearsomedragon...@gmail.com> writes:
> Please listen. In all the time I've spent in the coding community > (that's at least 7 years) and especially since I started paying > attention to the Python community (2 years), I have noticed a trend: > When one coder does something that another cannot understand, > frequently the other will assume the former is not only doing things > wrong, but is doing them _blatantly_ wrong.
I think you may be misinterpreting the message.
> At this point, I don't even believe in such a thing as a universal > "wrong way" and a "right way" to code that applies to every > circumstance. The way to solve a problem depends on the problem.
You'll find firm agreement on that in this group.
> When it comes to coding, there is not an absolute "right" way or > "wrong" way--unless we're talking about, say, stealing closed source > code without permission, or deliberately coding in a way that will > cause problems for the end user (like causing memory clogs or buffer > overflows and whatnot).
However, when it comes to a *specific*, mature programming language, there *are* right and wrong ways. Or, at least, there are ways encouraged or discouraged by the language, its interfaces, its style guides, and its community.
Which is very important: it's the rare program that is only ever read by one person in one context. Far more often, the same program needs to be read multiple times, by multiple people, in multiple contexts, over multiple iterations of maintenance. And for that to be feasible, it's very important to write the program the right way *for that language*.
Sticking to local conventions has a great deal of practical merit in the medium of human-to-human communication that we call “programming”. Progress depends on doing things differently; but maintainability depends on keeping unexpected differences to a minimum.
-- \ “The truth is the most valuable thing we have. Let us economize | `\ it.” —Mark Twain, _Following the Equator_ | _o__) | Ben Finney
>> If you use it a lot, it is likely 1) you have abused class syntax for >> what should have been a dict or 2) what you need is to override >> __getattr__/__getattribute__ and __setattr__
> Oh boy...here we go. :| > <sniprant>
ok, then what's your use case, AFAICT in the discussion here and previous ones, nobody has yet described a realistic and compelling situation where setattr/getattr is the best solution. That's why the discussion tended to end with "not used frequently enough"; simply because nobody can turn up with a use case to justify a new syntax, especially since all the proposed syntax are ugly (the most acceptable one, for me, is obj.[foo], still ugly but not as ugly as the others).
On Sat, 28 Nov 2009 03:38:38 -0800, The Music Guy wrote: > Please listen. In all the time I've spent in the coding community > (that's at least 7 years) and especially since I started paying > attention to the Python community (2 years), I have noticed a trend: > When one coder does something that another cannot understand, frequently > the other will assume the former is not only doing things wrong, but is > doing them _blatantly_ wrong.
That's because most of the time that assumption is correct.
50% of all coders are worse than average -- and in fact since the distribution of coding skill is unlikely to be normally distributed, it may very well be true that *more* than 50% of all coders are worse than average. Which means that, when faced with a coder you know nothing about except that he is trying to do something you can't understand, merely by playing the odds you have at least a 50:50 chance that he's doing something silly.
The coders who hang around forums casting judgement are more likely like to better than average -- they're not just code monkeys putting in their eight hours days cranking out boilerplate code. They usually know what they're doing. They are skillful and knowledgeable -- those who aren't don't last long: they either leave, or they learn and become knowledgeable. So when people on forums suggest something is a bad idea, statistics is on their side, to say nothing of reasoned judgement.
Most new ideas are bad ideas. Pure statistics again -- if an idea is any good, somebody has probably already had it, and it has become a standard tool that everyone uses. Breaking code up into subroutines is such a good idea, and nearly every programming language has some way of breaking code up into subroutines. But bad ideas keep coming up over and over again, as they're thought of, then rejected, then somebody else comes along and thinks of it again. The same old bad ideas keep being raised again and again.
> I have caught myself making that very > assumption many times in the past, and I've tried hard to build up an > immunity against the impulse to make that assumption.
Doing so reduces your chances of making uncommon false negatives at the cost of increasing your chances of making common false positives. Personally, I think it's a bad strategy, but that depends on just how much effort you put into giving every new idea a fair shake.
> At this point, I > don't even believe in such a thing as a universal "wrong way" and a > "right way" to code that applies to every circumstance.
Well duh :)
> The way to solve a problem depends on the problem.
Well duh again :D
But there are certain "standard", common, types of problems. Most problems are just variations on other problems. Very few problems are unique.
> When it comes to coding, there is not > an absolute "right" way or "wrong" way--unless we're talking about, say, > stealing closed source code without permission, or deliberately coding > in a way that will cause problems for the end user (like causing memory > clogs or buffer overflows and whatnot).
There is no need for "deliberately" in that sentence. If you cause problems like buffer overflows, you're doing it wrong. It's wrong whether you did so maliciously or through ignorance. Even if you document that it is subject to this failure mode ("don't do this"), it's still wrong.
Sometimes we do the wrong thing because sometimes it's more important to get a 99% solution today than a 100% solution next month, but it's still objectively buggy.
> All of this can be determined through common sense. And yet I continue > to see the attitude of "my solution is the ONLY solution to your > problem, and it doesn't matter if I don't even actually understand the > problem." Not everyone does this, but it is a frequent enough occurence > to be worth noting. If I had to pull a number out of my magic bag, I > would say 4 out of 10 resposes have at least a hint of this attitude, > and 2.5/10 where it is very obvious.
You say that as if it's a bad thing. I think it's a good thing -- most solutions are tried and tested, and conservatively sticking to solutions that are known to work is a successful solution:
* if you write code which took a lot of effort to understand, it will take a lot of effort to maintain;
* if you write code which only the creator understands, then if something happens to the creator, nobody will understand the code;
* debugging is harder than writing code in the first place, so if you write the cleverest code you possibly can, then you aren't clever enough to debug it.
[...]
> ...and I have one last thing to say. I feel very strongly that > metaclassing is a fiercely underestimated and largely untapped source of > good coding solutions.
There's a reason for that -- metaclasses are *clever*. Good solutions should be dumb enough that even the 50% of below-average coders can use them. Metaclasses are hard, and because they're hard, they're underutilized, and consequently people are unfamiliar with them. Because they're unfamiliar, that makes them even harder to understand, and so people avoid metaclasses -- a vicious circle, as you pointed out.
> >> If you use it a lot, it is likely 1) you have abused class syntax for > >> what should have been a dict or 2) what you need is to override > >> __getattr__/__getattribute__ and __setattr__
> > Oh boy...here we go. :| > > <sniprant>
> ok, then what's your use case, AFAICT in the discussion here and > previous ones, nobody has yet described a realistic and compelling > situation where setattr/getattr is the best solution. That's why the > discussion tended to end with "not used frequently enough"; simply > because nobody can turn up with a use case to justify a new syntax, > especially since all the proposed syntax are ugly (the most acceptable > one, for me, is obj.[foo], still ugly but not as ugly as the others).
Alright, I'm not sure if my last message about this came through, so I'm going to assume it didn't.
When I first started seeing @ show up in Python code, I said "what the heck is that? It looks so weird and _ugly_. I would never try to mess with that." But I started seeing it more and more, so I asked #python what it was. They told me about decorators, so I looked it up in the docs, and I thought the idea was interesting. It took me a while to figure out exactly how they worked--and judging from messages I've seen in #python a number of people have the same trouble understanding them.
My point is that any particular syntax would look ugly to you only because you haven't seen it in use enough, and haven't used it enough yourself. But of course you haven't--it's not currently a valid syntax. However, the ugliness would seem to go away after the syntax had been in use for a while. And again, the EXACT syntax of the feature can be adjusted until its "just right".
As for my specific use case, it's somewhat difficult to explain. The general idea was to isolate a pattern that I spotted repeated in several unrelated parts of my project. The pattern manifested itself as a set of 4-5 methods and/or properties on a class whose objects were designed to work in conjunction with other objects that fit a particular behavior. These other objects had methods and properties that were designed to interact with the first type of object in a similar but--how should I say--"inverted" fashion.
This pattern showed up in many different classes throughout the project, and not only that, but the code was very similar. I decided to try to eliminate some of the code redundancy by creating a base class for all the classes to derive from. That didn't worked out okay for some things, but not for others. I can't remember the exact details of the problem at this point, but I believe it had to do with the keying/indexing protocol (ie. __getitem__, __setitem__, etc.). I decided to keep the base class (and have since extended it), but decided that it wasn't enough--that's when I decided to try metaclassing. After some work I managed to recreate the object-to- object relationship pattern that kept showing up everywhere, but in a generic way that allowed for the names of methods and properties that composed the pattern to vary in name and in the names that they referenced from other objects. The code worked very well, and allowed for the pattern to be added to any class by using a single, short line of code (something along the lines of __class_attr = { key: value }). Not only that, but the metaclass code itself was comprised of less than a screenful of code after docstrings and comments had been removed. However, the code was (and still is) very difficult to follow simply because of the way getters and setters had to be used to generate the methods and properties.
P.s. Ben Finney, I appreciate your response, and I will get back to you, but I want to make sure I reply under the right circumstances or I'll end up putting my foot in my mouth. ^_^
On Sat, 28 Nov 2009 17:22:27 -0800, The Music Guy wrote: > As for my specific use case, it's somewhat difficult to explain. The > general idea was to isolate a pattern that I spotted repeated in several > unrelated parts of my project. The pattern manifested itself as a set of > 4-5 methods and/or properties on a class whose objects were designed to > work in conjunction with other objects that fit a particular behavior. > These other objects had methods and properties that were designed to > interact with the first type of object in a similar but--how should I > say--"inverted" fashion.
> This pattern showed up in many different classes throughout the project, > and not only that, but the code was very similar. I decided to try to > eliminate some of the code redundancy by creating a base class for all > the classes to derive from. That didn't worked out okay for some things, > but not for others. I can't remember the exact details of the problem at > this point, but I believe it had to do with the keying/indexing protocol > (ie. __getitem__, __setitem__, etc.). I decided to keep the base class > (and have since extended it), but decided that it wasn't enough--that's > when I decided to try metaclassing. After some work I managed to > recreate the object-to- object relationship pattern that kept showing up > everywhere, but in a generic way that allowed for the names of methods > and properties that composed the pattern to vary in name and in the > names that they referenced from other objects.
Removing code redundancy is all very well, but beware of turning into an architecture astronaut:
There is such a thing as over-generalisation -- if you're having to struggle to get the abstract code working abstractly enough, you're probably over-generalising.
> The code worked very > well, and allowed for the pattern to be added to any class by using a > single, short line of code (something along the lines of __class_attr = > { key: value }). Not only that, but the metaclass code itself was > comprised of less than a screenful of code after docstrings and comments > had been removed. However, the code was (and still is) very difficult to > follow simply because of the way getters and setters had to be used to > generate the methods and properties.
That's good evidence that you've over-generalised.
Okay, I'm having a really hard time telling which messages are getting on to the list and which ones aren't. Some of the messages I send show up in the comp.lang.python mirror in Google Groups, and some aren't. Others show up on the Groups mirror, but don't show up in Gmail, or show up in a different order. It seems the only way I can guarantee anything showing up on Groups is to post on Groups, but that makes it difficult because I can't see the messages in the thread that only appear in my inbox. Is there a quick fix for this, because it's getting pretty aggravating trying to figure out who heard what. I don't like mailing lists. :P