1

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 ...

robert
  • 4,612
  • 2
  • 29
  • 39
  • See also http://stackoverflow.com/q/4966509/3001761, http://stackoverflow.com/q/2350817/3001761, http://stackoverflow.com/q/2827623/3001761, ... – jonrsharpe Oct 07 '15 at 14:15
  • @jonrsharpe thanks, those links are helpful but don't really answer my question – robert Oct 07 '15 at 14:18
  • @Kay I think that's the same as what I have at the top of my question but all one one line :) – robert Oct 07 '15 at 14:18
  • @johnsharpe the first link you provide is "general advice" on how to implement this pattern - I am looking for an actual standard implementation – robert Oct 07 '15 at 14:20
  • @johnsharpe the second does not provide the constructor interface I am looking for – robert Oct 07 '15 at 14:20
  • @johnsharpe the final link is just an alternative way of doing what I'm already doing – robert Oct 07 '15 at 14:22
  • @johnsharpe it doesn't seem as though you took my question on board at all, you just searched for random posts that just "looked like" my one. – robert Oct 07 '15 at 14:22
  • @johnrsharpe yeah thanks, but it's not a duplicate. But anyway it looks like kirbyfan64sos below has an answer that differs with your "opinion". – robert Oct 07 '15 at 14:26
  • Thanks, I thought that was what the site was for. Sorry if I offended you with my mis-spelling - smack on the wrist for me! – robert Oct 07 '15 at 14:30

1 Answers1

1

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!

kirbyfan64sos
  • 10,377
  • 6
  • 54
  • 75
  • 1
    @robert You mean the extra line used for importing `argparse`? :D – kirbyfan64sos Oct 07 '15 at 14:24
  • Sorry - actually I'm re-reading it again ... yep I think that might be what I'm looking for! – robert Oct 07 '15 at 14:25
  • Does exactly what I want :) – robert Oct 07 '15 at 14:28
  • I'm actually very happy with this - it's like a new toy - not at all sure why you say it's icky - looking at the source for its implementation there isn't any additional cruft beyond just what's needed .. can set default vals as class vars too. If only there was a good way to specify mandatory attributes .... – robert Oct 07 '15 at 15:14
  • 1
    @robert that's easy enough; just subclass it and define them in `__init__` – jonrsharpe Oct 07 '15 at 21:32
  • Thanks John, was hoping for something nice & declarative like `_slots_` but that doesn't work on derived classes :( oh well there comes a point where you've got to say "good enough"! – robert Oct 08 '15 at 07:28