4

html2txt contains the following code:

class Storage: pass
options = Storage()
options.google_doc = False
options.ul_item_mark = '*'

I've not seen such an approach before. What's the benefit/use of this approach over setting up the attributes in __init__(), and is a class even necessary here?

Pyderman
  • 14,809
  • 13
  • 61
  • 106
  • 2
    Given the name it appears to be used an 'ad-hoc class': a bag of properties, for some localized meaning, without explicitly using a Dictionary. This avoids having to use proper values (eg. strings) for keys. Ruby has `ostruct` and JavaScript objects implicitly act as such. – user2864740 Feb 11 '16 at 03:30
  • 1
    Other use cases include dynamically overriding object methods/attributes or creating mock objects (duck-typing). – apex-meme-lord Feb 11 '16 at 03:39

2 Answers2

4

Suppose you want to store some collection of named data. You could use a dict but you like the look of dotted attributes in a class object. Just create the most boring class possible and use python's native attribute assignment to do the trick. It is usually a question of aesthetics.

tdelaney
  • 73,364
  • 6
  • 83
  • 116
1

If you know the attributes ahead of time you can use namedtuples for this kind of functionality.

From the python docs:

EmployeeRecord = namedtuple('EmployeeRecord', 'name, age, title, department, paygrade')
alexhb
  • 435
  • 2
  • 12
  • 1
    ...if you know all of the information in advance and nothing changes. – tdelaney Feb 11 '16 at 03:44
  • 1
    @tdelaney Not sure what you mean. You can dynamically add to a namedtuple as well. I could loop through a set of attribute names and attach attributes e.g. EmployeeRecord.home_address = '123 Main St.' Anyway, in OP's post the information IS known ahead of time. – alexhb Feb 11 '16 at 04:02
  • 2
    No, you can't (re your reply to @tdelaney). You can *if* you subclass `namedtuple`, but that's not how `namedtuple` is supposed to be used. You are not using it as a tuple, just as any old namespace. Use `SimpleNamespace` for that case, new in Python 3.3: [doc](https://docs.python.org/3/library/types.html#additional-utility-classes-and-functions) – gil Feb 11 '16 at 04:09
  • 1
    No, you cannot add anything dynamcally... its a `tuple` after all. You get one shot to create the objects by supplying the values to the constructor. No changes, no additions. – tdelaney Feb 11 '16 at 04:09
  • 1
    @alexhb `type(namedtuple)` is `` meaning only that it is a factory function. How about actually trying it? ` Foo=namedtuple('Foo', 'a b c');foo=Foo(1,2,3);foo.a=2` results in `AttributeError: can't set attribute`. – tdelaney Feb 11 '16 at 04:17
  • 1
    @tdelaney Give this a try: `type(EmployeeRecord)`. Once you construct the namedtuple as in `EmployeeRecord('alex', '29')` then you cannot add attributes on the fly. – alexhb Feb 11 '16 at 04:17
  • 1
    @alexhb - well sure, you can add attributes to the class object which makes it like most other class objects out there. How about `lxml.etree.XMLSchemaError` or even `os.walk`. You can add attributes to lots of things. – tdelaney Feb 11 '16 at 04:21
  • 1
    `collections.namedtuple` doesn't create a namedtuple. It creates a namedtuple creator. You get the namedtuple when you instantiate it. – tdelaney Feb 11 '16 at 04:24
  • 1
    @tdelaney Absolutely. And you're right, adding attrs to the namedtuple before it's instantiated is mostly useless. The boon and burden of duck typing. Maybe it's the statically-typed programmer in me, but when you have cases where the attributes are known I think it's probably more pythonic to just have a namedtuple. Self-documenting, less cruft, etc. Anyway, glad I said something because I did not know about SimpleNamespace. – alexhb Feb 11 '16 at 04:34