Open dimitern opened 7 years ago
Another way, that can also keep backwards compat a bit is to (ab)use slices for defaults as callables, eg:
class Record(fields.Tuple.Username[""].Created[:datetime.now].Revision[None].Active[False):
pass
or even with strings for more possibilities (the init function is made from a string, alike namedtuple, so this is possible):
class Record(fields.Tuple.Username[:"getpass.getuser()"].Created[:"datetime.now()"].Revision[None].Active["Revision!=None"):
pass
Actually both forms could be supported.
Anyway, doesn't attrs
already support default values from callables?
I was thinking of abusing the slice syntax at first :) Could be useful for things like validators, converters, or even docstrings, esp. if combined with your suggestion about supporting strings:
class Record(fields.Tuple
.WithoutDefault
.WithConstDefault["foo"]
.WithCallableDefault[:"datetime.now().isoformat()"]
.WithDocstring[None, """The doc"""]
.AllInOne["bar", """Bar doc"""]):
pass
r = Record(1)
assert r.WithDocString.__doc__ == """The Doc"""
assert r.WithCallableDefault == "2000-01-02T03:04:05"
Yeah, attrs
supports callable defaults and lots more, but I like the concise declarative style of fields
better I think :)
I'll look into it some more, cheers!
Well yes, fields
is not meant to replace attrs
, or even compete with it. As a matter of fact it precedes attrs
(it's practically a jab at characteristic). You may have guessed it, attrs
probably wouldn't exist if I hadn't done fields
xD
Intended use is very small classes (5 fields or less). If you can't fit it on one line then probably you shouldn't use fields
at all - the whole idea of extreme brevity become a moot point if you split the definition on multiple lines in ugly jquery chain style.
First let me say - great library! :) I've been evaluating it as well as
attrs
for a while now.I'd like to suggest a possible feature extension: allow
callable
defaults, which will let you do things like this:Using types as defaults IMO makes the code more readable. Also assuming the callable takes no arguments, it allows simple initialization at run-time (like with
datetime.now
).It's easy to do that with a simple sealer wrapper, like the one below:
What do you think?