The trouble with "dynamic attributes".

MRAB python at
Fri Sep 17 01:27:08 CEST 2010

On 16/09/2010 22:46, John Nagle wrote:
>   There's a tendency to use "dynamic attributes" in Python when
> trying to encapsulate objects from other systems. It almost
> works. But it's usually a headache in the end, and should be
> discouraged. Here's why.
> Some parsers, like BeautifulSoup, try to encapsulate HTML tag
> fields as Python attributes. This gives trouble for several reasons.
> First, the syntax for Python attributes and Python tags is different.
> Some strings won't convert to attributes. You can crash BeautifulSoup
> (which is supposed to be robust against bad HTML) by using a non-ASCII
> character in a tag in an HTML document it is parsing.
> Then there's the reserved word problem. "class" is a valid field
> name in HTML, and a reserved word in Python. So there has to be a
> workaround for reserved words.
> There's also the problem that user-created attributes go into the
> same namespace as other object attributes. This creates a vulnerability
> comparable to MySQL injection. If an attacker controls the input
> being parsed, they may be able to induce a store into something
> they shouldn't be able to access.
> This problem shows up again in "suds", the module for writing
> SOAP RPC clients. This module tries to use attributes for
> XML structures, and it almost works. It tends to founder when
> the XML data model has strings that aren't valid attributes.
> ("-" appears frequently in XML fields, but is not valid in an
> attribute name.)
> Using a dictionary, or inheriting an object from "dict", doesn't
> create these problems. The data items live in their own dictionary,
> and can't clash with anything else. Of course, you have to write
> tag['a']
> instead of
> tag.a
> but then, at least you know what to do when you need
> tag['class']
> "suds", incidentally, tries to do both. They accept both
> item.fieldname
> and
> item['fieldname']
> But they are faking a dictionary, and it doesn't quite work right.
> 'fieldname' in item
> works correctly, but the form to get None when the field is missing,
> item.get('fieldname',None)
> isn't implemented.
> Much of the code that uses objects as dictionaries either predates
> the days when you couldn't inherit from "dict", or was written by
> Javascript programmers. (In Javascript, an object and a dictionary
> are the same thing. In Python, they're not.) In new code, it's
> better to inherit from "dict". It eliminates the special cases.
For the work on updating the re module there was a discussion about
whether named capture groups should be available as attributes of the
match object or via subscripting (or both?). Subscripting seemed
preferable to me because:

1. Adding attributes looks too much like 'magic'.

2. What should happen if a group name conflicts with a normal attribute?

3. What should happen if a group name conflicts with a reserved word?

For those reasons the new regex module uses subscripting. It's more
Pythonic, IMHO.

More information about the Python-list mailing list