From: John Nagle on
On 7/2/2010 1:54 AM, Gregory Ewing wrote:
> WANG Cong wrote:
>
>> Yeah, my point is why setattr() for dynamic attributes while assignments
>> for static attributes?
>
> If you mean using exactly the same syntax for both, that would
> require making the static case more verbose, e.g. instead of
>
> foo.blarg
>
> you would have to write something like
>
> foo.("blarg")
>
> just to allow for the possibility of writing
>
> foo.(some_arbitrary_expression)

Instead of dynamically adding attributes, there's another option:
deriving a class from "dict":

class HTMLtag(dict) :
def __init__(self, tagtype) :
self.tagtype = tagtype

def __str__(self) : # generate source HTML tag
return("<" + self.tagtype + " "
+ " ".join(map(lambda item: '%s="%s"' % item,
self.items()))
+ ">"


tag1 = HTMLtag(a)
tag1['href'] = "http://www.example.com"
tag1['class'] = "adurl"

s = str(tag1) # converts to string


This has some advantages. The elements of the dictionary aren't
in the same namespace as the attributes of object, so there's
no problem with name clashes. Nor is there a problem with
reserved words. BeautifulSoup stores HTML tag attributes as
object attributes, and they have to special case things like
"class".

You can iterate over all the elements of the dictionary (as the
"__str__" function does above) without interference from
attributes which aren't data items.

There's no problem with values that aren't valid attribute
strings. (Python 2.x won't accept Unicode attributes, for example.)

There's no risk of security injection problems because external
data overrode a member name or some crucial data attribute.

If you find yourself having to write code to avoid any of those
problems, like prefixing dynamic attribute names with some symbol to
avoid name clashes (or realize, after reading this, that your code
has a vulnerability because it's not doing that), it may be better
to inherit from "dict" rather than setting attributes explicitly.

John Nagle