简体   繁体   中英

Standard Python base class as a container for arbitrary attributes

Just asking this question because it seems to be a pattern that emerges quite regularly, and I'm wondering if anybody is aware of a standard library feature that supports this, or a one-liner perhaps that does something equivalent.

If I wanted to define a class for passing around data, that can contain arbitrary attributes, to be set when constructing I could do something like this:

>>> class Splat:
        def __init__(self, **args):
            for k, v in args:
                setattr(self, k, v)

and then use it like this:

>>> s = Splat(attr1='burp', attr2='gurt', attr3='sint')
>>> vars(s)
{'attr2': 'gurt', 'attr3': 'sint', 'attr1': 'burp'}

It's a pattern I've seen used in the python standard library ( ssl.wrapSocket or something in there if memory serves) and I'd imagine it would be useful enough in general that there could be a commonly used python idiom or mixin that I could leverage rather than having to create my own one whenever I need it.

I know it's only a four liner to include this when I need, but in the interests of parsimony I'd like to know if there's a 0 or at least 1-liner variant I could use. Like this maybe:

s = TheBaseClass({'attr2': 'gurt', 'attr3': 'sint', 'attr1': 'burp'})

or

class Splat(TheBaseClass):
    pass

Some might be quick to jump in and say "use a dict" instead, but I'm thinking of usecases where one might wish to mock an existing object-type (duck typing) and also to infer that it is a specific "type" (like if this feature were just used as a mixin).

Edit: Similarly, an issue with a construction such as s = type('Splat', (), {'attr2': 'gurt', 'attr3': 'sint', 'attr1': 'burp'}) is that I don't get to declare it, or get much in the way of type safety ...

This is a bit like hitting a nail with a bulldozer...but argparse defines a Namespace class that does this:

import argparse
print(argparse.Namespace(a=1, b=2))

You can always derive from it:

import argparse
class X(argparse.Namespace): pass
print(X(a=1, b=2))

However, I wouldn't really recommend that you do this, since it's kind of...icky...

At least you get __str__ and __repr__ for free!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM