I somewhat accidentally discovered that you can set 'illegal' attributes to an object using
foo = Foo()
setattr(foo, "bar.baz", "this can't be reached")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Foo' object has no attribute 'bar'
def __setattr__(self, attr, value):
if not re.match(r"^\w[\w\d\-]+$", attr):
raise AttributeError("Invalid characters in attribute name")
I think that your assumption that attributes must be "identifiers" is incorrect. As you've noted, python objects support arbitrary attributes (not just identifiers) because for most objects, the attributes are stored in the instance's
__dict__ (which is a
dict and therefore supports arbitrary string keys). However, in order to have an attribute access operator at all, the set of names that can be accessed in that way needs to be restricted to allow for the generation of a syntax that can parse it.
Is it simply assumed that, if you have to use setattr to set the variable, you are going to reference it via getattr?
No. I don't think that's assumed. I think that the assumption is that if you're referencing attributes using the
. operator, then you know what those attributes are. And if you have the ability to know what those attributes are, then you probably have control over what they're called. And if you have control over what they're called, then you can name them something that the parser knows how to handle ;-).