0

I've seen Python objects with attributes like %values. I can't access such attributes, as they raise a SyntaxError. They also seem to require setattr to be created without a SyntaxError:

class A(object):
    pass
a = A()
setattr(a, "%values", 42)
a.%values    # results in SyntaxError: invalid syntax
class B(object):
    def __init__(self):
        self.%values = 42    # results in SyntaxError: invalid syntax

Does the % have any purpose or meaning here? Why can %values be set using setattr, but otherwise raises a SyntaxError?

user2561747
  • 1,333
  • 2
  • 16
  • 39
  • why would you ever make a variable with a % sign in it? % is an operator which is why you are getting the syntax error. just use getattr() to access it – John Ruddell Mar 20 '15 at 23:42

2 Answers2

1

Does the % have any purpose or meaning here?

Most likely it is precisely to prevent you from accessing those attributes using regular dot notation, because, as you have seen, you can't. This discourages you from using them, making them in some way "private" to whatever application is using them. There are probably better ways to achieve this, though. I would call it a smell if I saw code like this.

Why can %values be set using setattr, but otherwise raises a SyntaxError?

Attributes are stored in a dictionary, and the dictionary keys can be anything. They don't have to follow the same rules as Python identifiers; the most Python does is verify they are strings. (Some older versions of Python do enforce that names passed to setattr are valid Python identifiers, but this was removed from the language some time ago.)

kindall
  • 178,883
  • 35
  • 278
  • 309
  • 1
    Worth noting that you *can* access them in a roundabout way (most likely, this was some weird access-control attempt), with `getattr(a, "%value")` or `a.__dict__["%value"]` – jedwards Mar 20 '15 at 23:40
1

%values is not a valid identifier in Python. As discovered in this question, setattr() just changes an object's __dict__ attribute directly, so that doesn't matter. object.__setattr__() is called when normal variable assignment is attempted, but it also doesn't seem to care about valid identifiers:

class A(object):
    pass
a=A()
a.__setattr__("%val",1) #works
print a.__dict__ #prints "{'%val': 1}"

setattr() seems to call the objects __setattr__() function if it exists before modifying its __dict__:

class A:
    def __setattr__(self,name,value):
        print "__setattr__ called"
a=A()
a.val=1 #prints "__setattr__ called"

In actual code, though, I don't think there's any reason to set __dict__ or call __setattr__() or setattr() to make it look like a variable name starts with a percent sign.

Community
  • 1
  • 1
KSFT
  • 1,774
  • 11
  • 17