-
-
Notifications
You must be signed in to change notification settings - Fork 383
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
Simple way to make individual attributes immutable? #133
Comments
Well, hm. It would be |
This turns out to be super useful when retrofitting existing codebases to use attrs. |
I suggested |
Quoth @Lukasa: I’d merge a (good) PR. ;) |
Could you provide some pointers as to where one would start, and what a good PR might look like? |
Maybe @Tinche can be more helpful but I'd guess that we could adapt The reason for my handwavevey delegation is mostly b/c I dunno. :) |
I'm not really sure how you'd go about implementing this. One way: for a field
This is how it's normally done when using manual classes. Another way would be to install a custom
This will impose a penalty on every assignment and every I think the first approach is a little better. Inheritance needs to be taken into account as well. Maybe there are more ingenious approaches, so comments welcome :) |
I was approaching it from the descriptor angle, to be honest. I'm not interested in blocking serious workaround, just making readonly properties relatively easy: class Attribute:
def __set__(self, obj, value):
raise FrozenAttributeError() Would that not be a direction to start in? |
How about using having a frozen instance and use evolve for mutable attributes? Too much overhead? |
Something like this, you mean? It's an interesting approach, but it won't work with slot classes. Maybe it could be made to support slot classes with a little more investigation though. |
Gah, if I ever meet @gvanrossum at a conference, I will buy him a drink and then continue to complain for 10 minutes about how immutability sucks in Python. |
Alright, I've been poking at frozen attributes for slot classes for a few hours now. Good news: I actually understand Python descriptors now! (I think.) 🤓 Let me elaborate. Slot classes store their instance contents in a hidden array. As far as I can tell, this space is basically inaccessible directly from Python. This is different from normal classes, which use When a slot class is defined, this space is allocated somewhere and a descriptor is made for each attribute. This descriptor is the only way to actually access this space. The descriptors are then placed into the class These descriptors are of type I don't really know how to write C extensions, nor am I sure attrs would allow C extensions. However writing a descriptor in C that duplicates It's also possible I've made a mistake somewhere, this stuff isn't exactly the simplest. |
I think this is out of question for the reason alone that it will explode in our faces on anything that isn’t CPython, correct? |
I have a pure Python proof of concept, but it slows down attribute access by a lot. Presumably PyPy would take care of the speed bump. Maybe I'll do some benchmarks. |
Hm, there's a performance penalty on PyPy too. 0.10 ns +- 0.00 ns vs 2.46 ns +- 0.07 ns. The numbers are so small I'm not even sure the measurements are good. |
Whatever y’all do: it must not affect the performance of other at all. I’m not gonna stop people driving around with handbrakes on but don’t take any hostages. :) |
It seems pretty clear to me that this isn't going to affect the performance of other cases. We can use our favorite tool to prevent this - subclassing! :)
This would be a performance hit for the attributes that use it, of course, but, that's fine; the purpose of this is mostly just to prevent errors anyway, and I bet this is exactly the sort of no-op that PyPy will happily JIT away. And for the attributes that don't use it, nothing would change. |
Separate thought based on investigating this implementation - |
Ugh, Is the descriptor approach possible before we stop shaving off Attribute definitions? FWIW, I could live with shaving them off if someone uses P.S. I don’t believe in blackmailing but I’ve taken a screenshot of your suggestion to use subclassing just in case. ;) |
Yes, we'll need descriptors for this. I don't see why we'd use
What does this mean? |
I meant “start”. |
Ah. Yes it could be done, by making |
2017-08-30 I’d say this can wait but I also don’t care so dunno if that counts. :D |
I've started picking away at this over at #172. |
@thedrow thats what name-mangled "private" variables are for |
@RonnyPfannschmidt if you're talking about:
Then its not the same thing unfortunately. People want this instead:
Where abc cannot be changed once its been initialized. |
Just checking in to say that there's still plenty of demand for this |
Everyone interested in this please look at #645. |
…and more importantly #660 which implements all of this. |
I believe this is fixed. |
I'm a bad functional programmer and want to mutate parts of my classes. But it'd be nice if there were still a way to mark the parts of my class that are immutable as being immutable in a few key strokes. I usually won't bother if I have to work for it (I'm also lazy), but might catch some bugs. It seems this fits into attrs' general style.
attr.ib(readonly=True)
? Could be implemented as either a__setattr__
hook likefrozen
, or with aproperty
.The text was updated successfully, but these errors were encountered: