-
-
Notifications
You must be signed in to change notification settings - Fork 372
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[RFC] Inconvenient defaults? #487
Comments
"we could make import attrs Python 3 only." -> +1. "It would also allow us to embrace enums as part of our API." -> That would be awesome. |
I absolutely agree with your point on I'm also in favour of Python3-only
A question: My main issue with Thanks for all the amazing work! |
No, but you could probably use metaclasses and our programmatic interface (make_class) to build it yourself? |
In a world of AWS Lambda and other RAM-second based billing systems, making "slots=True" the default will literally save people money (since it uses less RAM, and avoids pointless dict creation for each instance). If it fails, then folks are likely to get noisy exceptions that a few asked-and-answered questions on Stack Overflow will teach them to resolve with "slots=False". |
Could even seed SO with a couple of self-answered Q&A covering common error cases where |
I tend to agree; it just goes a bit against |
My feelpinion: |
Disagree here. I use attrs classes a lot in my data analysis work, and often I'll have something expensive I need to do with the arguments passed in at initialization. I absolutely want to do that expensive thing exactly once for each instance, and AFAIK I have to do it as something like:
With That being said, I have no idea whether my needs here at all represent the majority of use-cases. |
I love myself some value types but It just doesn’t fit Python too well. But IIRC we’ve decided on an own function for it? |
I agree with Oh, and I think that @bskinn's argument against |
Possibly, will look into it. |
The reason why it's called And yes, |
Did we? Where can I read about that? |
It's gonna be |
It’s working 😱! Thank you so much @berislavlopac! ❤️ |
Keep up the good work! 😉 |
I actually think I agree that a default |
Just a thought -- if we're using separate decorators for defining frozen and mutable classes, perhaps the former can have |
Definitely makes sense to me for That could be one distinction between (a possibly yet-again-renamed) |
I also agree that
do
I wonder if this pattern is common enough to merit an example in the documentation. Note that these derived attributes still participate in hash, cmp, etc. unless you turn them off (#310). |
On one hand, I like this approach, as it provides a number of different ways to skin this cat. On the other, I feel this goes against "one obvious way to do it", introducing simply too many combinations to keep in mind:
So I'm not sure. 😆 Overall, I think I'm leaning slightly towards simplicity:
Especially if there are more differences between the two methods than just the default values of |
Yeah. I don't think |
Yeah there's not gonna be any more diversions. It's bad enough to have |
Not to derail an excellent conversation about mutability, but has For instance, in my own little world, I can't think of a single case where, given the type
I would ever want to allow empty strings or lists for the attributes where I did not specifically provide a default. To me, making something optional is the same thing as providing a default, and vice-versa - under all other circumstances (well, at least for strings and collections types), an empty value is a sign of failure. Obviously I can write validators for each of these items, but that ends up being at least 2 extra lines in the class definition for each attribute, or a single, very long line using I am probably totally wrong about all this, and would love to have it explained to me why. But if I'm not, may I suggest adding a flag to the decorator that, if provided, enables this basic level of validation for all Again, I apologize for jumping into this ongoing conversation about better defaults - this is probably a simple feature request. But as it seems like default behavior to me, I couldn't resist. Thanks for an incredible project that has made programming with classes/typing in Python literally 500% more pleasant! |
@petergaultney That sounds a bit off-topic for this thread, which is more about cleaning up the API around existing functionality. You're asking for a new feature, which you've filed as #495; it'll be easier to track that conversation there. |
Thanks for this effort, great stuff. I would humbly submit #391 for consideration. Stripping private attrs should not happen by default and instead be configurable with |
We are about to standardize on |
Well, I'm annoyed of typing And I've been cranking out PRs to fix all things that I want fixed before The last big remaining thing are pre-attribute |
Perhaps a solution might be a "templating" approach, e.g. with some kind of a my_template_1 = AttrsTemplate(auto_attrib=True)
my_template_2 = AttrsTemplate(auto_attrib=True, auto_exc=True)
@attr.s(template=my_template_1)
class Foo:
...
Oooh I just needed that recently, ended up using metadata to denote "mutability" of an attribute. |
Work has started in #645! |
@berislavlopac in theory the templating approach can be accomplished by meta-decorators, right?
I wonder if either documenting this pattern or providing some sugar for it, e.g.
|
Excellent point, haven't though of this approach -- it would definitely be useful to at least be documented if not implemented in this way. |
@berislavlopac @petergaultney I use this approach all the time (https://github.com/Tinche/flattrs/blob/master/src/flattr/_fb_attrs.py#L35). Note that it needs special boilerplate if you're using mypy, and mypy doesn't perfectly support it. |
Perhaps attr.ib(on_setattr=validate) would be a little more concise? |
That’s not really an issue since it’s gonna be the default in upcoming APIs. I don’t think we need to pollute our APIs with any sugar for it in the meantime. |
You can simply use >>> from functools import partial
>>>
>>> auto = partial(attrs, auto_attribs=True, auto_exc=True)
>>>
>>> @auto(frozen=True) # additional parameters
... class Foo:
... foo: int
...
>>> @auto # no parameters and no parentheses
... class Bar:
... bar: str
...
>>> Foo?
Init signature: Foo(foo: int) -> None
...
>>> Bar?
Init signature: Bar(bar: str) -> None
... You can even stack these: >>> frozen = partial(auto, frozen=True) Given how easy and readable and pythonic this is, I think having the least magical defaults is very reasonable. Perhaps with the exception of Mypy is the bigger problem here, as it currently doesn't understand P.S. I personally would like to be able to drop parentheses on @attrs
class Foo:
foo = attrib |
Sadly the mypy angle ruined this approach that I used to use all the time. :( |
This partial application decorator-forwarding usecase can be managed with a micro-plugin for mypy - you basically need something that says:
What this doesn't support is things like frozen - however the mypy attrs plugin itself could be trivially rewritten to expose those parameters directly for these sorts of mypy plugins. @hynek do you think mypy would accept a PR to make the built-in plugin more directly reusable? This whole mess of plugin code could probably be rewritten to be a one-liner that 'registers' a decorator with the mypy plugin. |
I've opened an issue asking for this almost two years ago: python/mypy#5406 FWIW, #650 is of interest here too. |
by the way, while assignment doesn't make mypy happy, importing under a different name does: if TYPE_CHECKING:
from attr import attrs as slotted
else:
slotted = functools.partial(attrs, slots=True) |
one thing which breaks some functional programming stuff, is the fact you can't do bracketed lookup with attrs objects
means you can't do functional lenses, lookPath, assocPath, dissocPath, evolvePath, are all legit, makes me miss Ramda! |
You can always implement your own |
worked like a charm, thanks for reminding me, that would be a fun default to add! |
Please check out #666 y'all. |
So FTR, NG APIs will ship as stable in 21.1, now is the last chance to ask for changes in APIs that are annoying. So far there's #705 but I'm sure there might be more? To be clear: define/mutable/frozen/field are set in stone now. But there's a buttload of other APIs that may benefit from polish? |
I just want to say thanks for |
As part of “Project
import attrs
” (see also #408) we get a unique opportunity to change default options/behaviors that grew over the years but couldn't be fixed due to backward-compatibility restrictions.The rough plan is create a new, friendlier API on top of
@attr.s
andattr.ib()
that won't go anywhere.The following is cast in stone:
auto_attribs=True
The following would be really nice to have:
What else is bugging you?
One thing that I just can't make up my mind is related to #223: should we make
slots=True
the default? I’m quite confident that in 99,9% of cases it's the right thing to do and will guide people to write better classes.However on the other hand, our approach of rewriting classes breaks in certain scenarios, usually involving metaclasses.
So the question is, whether we want to tolerate a higher rate of bogus bug reports/help requests or make the default case nicer?
I welcome your input.
Finally a controversial idea: we could make
import attrs
Python 3 only. There isn't much baggage we'd get rid of but there is some and 2020 is less than a year ahead. It would also allow us to embrace enums as part of our API.The text was updated successfully, but these errors were encountered: