Why is there no natural syntax for accessing attributes with namesnot being valid identifiers?

  • Thread starter Piotr Dobrogost
  • Start date
P

Piotr Dobrogost

The discussion of enlarging the scope of 'identifier' is not relevant as
you are not proposing that. In particular, you are not asking that
obj.value-1 get the 'value-1' attribute of obj.
Right.

The discussion of keystrokes is also a side-track.

To great degree, yes. Having said that I find extra 11 keystrokes needed toaccess some attributes to be a freaking big and unjustifiable number.
What you are proposing, I believe, is a new grammatical category:
attribute-name := identifier or string-literal. This would break the
symmetry of the grammatical form identifier '.' identifier and change it
to the asymmetrical identifier '.' attribute-name, and that is the

Nice description.
To put it another way, how does 'obj' get the non-standard attribute
'value-1', when obj is a module or class? The workaround given above for
module attributes will not work for classes.

I'm not sure I see your point. Do you mean that being inside class declaration there's no name that referrs to the current namespace (the way __globals__ refer to module's namespace) thus we can't use proposed syntax to access non-standard attributes from this namespace?
Not really. As others have pointed out, getattr is the preferred way to
get the value of an attribute when you have an object with attributes
and a run-time-only reference to the name in a string variable.

Yes, and I think it's very unfortunate in itself. Attribute access is fundamental operation and it's not accident that "operator" for this action is very concise in many languages being one char only. Having to switch to global function to access attribute in case its name is known only at run time is very awkward both when writing and reading code.
It would also be the case that "obj.'value' is obj.value", so the
proposal *would* add duplication.

This is not a big deal and that's what you get when someone had already decided that in expression a.b, b is treated literally.


Regards,
Piotr
 
P

Piotr Dobrogost

Perhaps you should look
at different ways of spelling your identifiers? Why can't you use an
underscore instead of a hyphen?

So that underscore could be left for use inside fields' names?
However I think we could use some unique Unicode character for this instead hyphen as long as Python allows any alphanumeric Unicode character inside identifiers which I think it does...

Regards,
Piotr
 
E

Ethan Furman

So that underscore could be left for use inside fields' names?
However I think we could use some unique Unicode character for this
instead hyphen as long as Python allows any alphanumeric Unicode
character inside identifiers which I think it does...

Yes, although I don't remember at which version that became true...
 
D

Dennis Lee Bieber

Piotr said:
Attribute access syntax being very concise is very often preferred
to dict's interface.

It is not "very concise". It is slightly more concise.

x = obj.value1
x = dct['value1']

You have saved 3 keystrokes. That is not a significant enough savings to
create new syntax. Remember the Python philosophy that there ought to be
one way to do it.

Its a more fundamental problem than that:
It emerges from the OP's second post) that he wants '-' in the attributes.
Is that all?

Where does this syntax-enlargement stop? Spaces? Newlines?

Spaces? I present to you two FORTRAN statements

DO 10 I = 3 . 14159
and
DO10I = 3 , 1 4 1 5 9

Which is the loop and which is the assignment?
 
N

Ned Batchelder

So that underscore could be left for use inside fields' names?
However I think we could use some unique Unicode character for this instead hyphen as long as Python allows any alphanumeric Unicode character inside identifiers which I think it does...

Regards,
Piotr

You object to typing [''] but you don't mind typing an unusual Unicode
character?

--Ned.
 
R

Rotwang


Unless we compare with what we have now, which gives 9 (without space) or 10 (with space):
x = obj.'value-1'
x = getattr(obj, 'value-1')
That is not a significant enough savings to create new syntax.

Well, 9 characters is probably significant enough saving to create new syntax but saving these characters is only a side effect and is not the most important aspect of this proposal which leads us to the next point.
Remember the Python philosophy that there ought to be one way to do it.

Funny you use this argument against my idea as this idea comes from following this rule whereas getattr goes against it. Using dot is the main syntax to access attributes. Following this, the syntax I'm proposing is much more in line with this primary syntax than getattr is. If there ought to be only one way to access attributes then it should be dot notation.

I believe that you are missing the point of getattr. It's not there so
that one can use arbitrary strings as attribute names; it's there so
that one can get attributes with names that aren't known until run time.
For this purpose the dot-notation-with-quotes you suggest above is not
good enough. For suppose e.g. that one does this:

name = 'attribute'
x.name

How would the interpreter know whether you're asking for getattr(x,
name) or getattr(x, 'name')?
 
T

Terry Reedy


Opinion, not universally shared by developers, or 'good thing only as
long as kept obscure'.

In a later post (after you wrote this) I explained that standard names
are not always accessed with a dot, and that uniformity is impossible.

More opinion. I am sure that I am not the only developer who disagrees.
The obvious thing to do is to either raise this on python ideas, or if
you're that confident about it raise an issue on the bug tracker with a
patch, which would include changes to unit tests and documentation as
well as code, get it reviewed and approved and Bob's your uncle, job
done.

I think the latter would be foolish. Syntax changes have a high bar for
acceptance. They should do more than save a few keystrokes. Use of new
syntax makes code backward incompatible. New or changed Python modules
can be backported (as long as they do not use new syntax ;-) either
privately or publicly (on PyPI).

3.2 had no syntax changes; 3.3 one that I know of ('yield from'), which
replaced about 15-20 *lines* of very tricky code; 3.4 has none that I
can remember.
 
E

Ethan Furman

More opinion. I am sure that I am not the only developer who disagrees.
+1



I think the latter would be foolish. Syntax changes have a high bar for acceptance. They should do more than save a few
keystrokes.

+1
 
T

Terry Reedy

To great degree, yes. Having said that I find extra 11 keystrokes
needed to access some attributes to be a freaking big and
unjustifiable number.

Given that there is almost no need to ever use operator chars in
attribute names and given that syntax changes have the major undesirable
consequence of backward incompatibility, I find it to be a small and
inconsequential number.
Nice description.

The module workaround, which I find pretty ugly, is this:
True

I have not checked that the import trick will work when a module is
imported, but I believe it will.
I'm not sure I see your point. Do you mean that being inside class
declaration there's no name that referrs to the current namespace
(the way __globals__ refer to module's namespace) thus we can't use
proposed syntax to access non-standard attributes from this
namespace?

Right. Class objects are not created until after the class code runs.
Yes, and I think it's very unfortunate in itself.

Do you prefer obj.__dict__['name'] to getattr(obj, 'name')?
 
S

Steven D'Aprano

Right. If there's already a way to have attributes with these
"non-standard" names (which is a good thing)

No it is not a good thing. It is a bad thing, and completely an accident
of implementation that it works at all.

Python does not support names (variable names, method names, attribute
names, module names etc.) which are not valid identifiers except by
accident. The right way to handle non-identifier names is to use keys in
a dictionary, which works for any legal string.

As you correctly say in another post:

"attribute is quite a different beast then key in a dictionary"

attributes are intended to be variables, not arbitrary keys. In some
languages, they are even called "instance variables". As they are
variables, they should be legal identifiers:

spam = 42 # legal identifier name
spam\n-ham\n = 42 # illegal identifier name


Sticking a dot in front of the name doesn't make it any different.
Variables, and attributes, should be legal identifiers. If I remember
correctly (and I may not), this issue has been raised with the Python-Dev
core developers, including Guido, and their decision was:

- allowing non-identifier attribute names is an accident of
implementation;

- Python implementations are allowed to optimize __dict__ to prohibit non-
valid identifiers;

- but it's probably not worth doing in CPython.

getattr already enforces that the attribute name is a string rather than
any arbitrary object.

You've also raised the issue of linking attribute names to descriptors.
Descriptors is certainly a good reason to use attributes, but it's not a
good reason for allowing non-identifier names. Instead of writing:

obj.'#$^%\n-\'."'

just use a legal identifier name! The above is an extreme example, but
the principle applies to less extreme examples. It might be slightly
annoying to write obj.foo_bar when you actually want of obj.'foo.bar' or
obj.'foo\nbar' or some other variation, but frankly, that's just too bad
for you.

As far as descriptors go, you can implement descriptor-like functionality
by overriding __getitem__. Here's a basic example:

class MyDict(dict):
def __getitem__(self, key):
obj = super(MyDict, self).__getitem__(key)
if hasattr(obj, '__get__'):
obj = obj.__get__(self)


which ought to be close to (but not identical) to the semantics of
attribute descriptors.

While I can see that there is some benefit to allowing non-identifier
attributes, I believe such benefit is very small, and not enough to
justify the cost by allowing non-identifier attributes. If I wanted to
program in a language where #$^%\n-\'." was a legal name for a variable,
I'd program in Forth.
 
N

Neil Cerutti

Taking into account that obj.'x' would be equivalent to obj.x
any attribute can be accessed with the new syntax. I don't see
how this is not unified access compared to using getattr
instead dot...

I thought of that argument later the next day. Your proposal does
unify access if the old obj.x syntax is removed.
 
P

Piotr Dobrogost

I thought of that argument later the next day. Your proposal does
unify access if the old obj.x syntax is removed.

As long as obj.x is a very concise way to get attribute named 'x' from object obj it's somehow odd that identifier x is treated not like identifier but like string literal 'x'. If it were treated like an identifier then we would get attribute with name being value of x instead attribute named 'x'. Making it possible to use string literals in the form obj.'x' as proposed this would make getattr basically needless as long as we use only variable not expression to denote attribute's name.
This is just casual remark.


Regards,
Piotr
 
R

Rotwang

[...]

I thought of that argument later the next day. Your proposal does
unify access if the old obj.x syntax is removed.

As long as obj.x is a very concise way to get attribute named 'x' from
object obj it's somehow odd that identifier x is treated not like
identifier but like string literal 'x'. If it were treated like an
identifier then we would get attribute with name being value of x
instead attribute named 'x'. Making it possible to use string literals
in the form obj.'x' as proposed this would make getattr basically
needless as long as we use only variable not expression to denote
attribute's name.

But then every time you wanted to get an attribute with a name known at
compile time you'd need to write obj.'x' instead of obj.x, thereby
requiring two additional keystrokes. Given that the large majority of
attribute access Python code uses dot syntax rather than getattr, this
seems like it would massively outweigh the eleven keystrokes one saves
by writing obj.'x' instead of getattr(obj,'x').
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,535
Members
45,007
Latest member
obedient dusk

Latest Threads

Top