Re: [Python-ideas] Support other dict types for type.__dict__

Hum, after thinking twice, using a "frozendict" for type.__dict__ is maybe overkill for my needs (and intrused as noticed Nick). Attached patch for Python 3.3 is a simpler approach: add __final__ special value for class. If this variable is present, the type is constant. Example: --- class Test: __final__=True x = 1 Test.x = 2 # raise a TypeError Test.new_attr = 1 # raise a TypeError del Test.x # raise a TypeError --- There are various ways to deny the modification of a class attribute, but I don't know how to block the removal of an attribute of the addition of a new attribute without my patch. -- My patch is just a proof-of-concept. For example, it doesn't ensure that values are read-only too. By the way, how can I check that "a value is constant"? Except builtin immutable types, I suppose that the only way is to call hash(obj) and excepts an expect a TypeError. Victor

On 2012-02-24, at 9:29 PM, Victor Stinner wrote:
-1 on this. The next move would be adding friend classes and protected methods ;) __setattr__ works perfectly for those purposes. Moreover, you can emulate your idea on unpatched python by using metaclasses. - Yury

Ned Batchelder wrote:
That is silly. That alleged "Python answer" is like telling people that they don't need test frameworks or debuggers because the "Python answer" for people wanting to debug their code is not to write buggy code in the first place. Python has read-only data structures: tuple, frozenset, str, etc. If you ask yourself why Python has immutable types, it might give you a clue why Victor wants the ability to create other immutable types like frozendict, and why "don't modify them" is not a good enough answer: - Immutable types can be used as keys in dicts. - Immutable types protect you from errors. While you might intend not to modify a data structure, bugs do happen. Immutability gives you an immediate exception at the exact time and place you attempt to modify the data structure instead of at some arbitrary time later far from the actual bug. Python has excellent support for read-only data structures, so long as you write them in C. -- Steven

On 2012-02-26, at 00:05 , Steven D'Aprano wrote:
- Immutable types can be used as keys in dicts.
*technically*, you can use mutable types as dict keys if you define their __hash__ no? That is of course a bad idea when the instances are *expected* to be modified, but it should "work".
- Immutable types protect you from errors. While you might intend not to modify a data structure, bugs do happen.
Immutables are also inherently thread-safe (since thread safety is about shared state, and shared immutables are not state). Which is a nice guarantee.
Python has excellent support for read-only data structures, so long as you write them in C.
There's also good support of the "consenting adults" variety (use _-prefixed attributes for the actual state and expose what needs to be exposed via properties and methods). That can be simplified with a custom descriptor type which can only be set once (similar to java's `final`), it would be set in the type's constructor and never re-set from this.

On Feb 26, 2012 1:35 AM, "Masklinn" <masklinn@masklinn.net> wrote:
I wouldn't say this is necessarily a bad thing at all. It just depends what defines the object. If an instance represent a specific object (e.g. a database record) you wouldn't expect the hash to change if you modified an attribute of it, since the instance still represents the same object.
you write them in C.
Maybe I'm missing something here, but what's wrong with just using __getattr__, __setattr__ and __delattr__ to restrict access?

On Sat, Feb 25, 2012 at 6:32 PM, Masklinn <masklinn@masklinn.net> wrote:
On 2012-02-26, at 00:05 , Steven D'Aprano wrote:
- Immutable types can be used as keys in dicts.
Not always; for example, you can't use a tuple of lists, even though the tuple itself is immutable.
Not even a bad idea, if you define the hash carefully. (Similar to java final.) Once hash(obj) returns something other than -1, it should return that same value forever. Attributes which do not contribute to the hash can certainly still change. That said, I would be nervous about changes to attributes that contribute to __eq__, just because third party code may be so surprised.
-jJ

An easy way to create immutable instances is 'collections.namedtuple': X = namedtuple("X", "a b") x = X(a=4, b=2) x.a + x.b # fine x.a = 5 # AttributeError: can't set attribute x.c = 5 # AttributeError: 'X' object has no attribute 'c' Tricks using 'object.__setattr__()' etc. will fail since the instance doesn't have a '__dict__'. The only data in the instance is stored in a tuple, so it's as immutable as a tuple. You can also derive from 'X' to add further methods. Remember to set '__slots__' to an empty iterable to maintain immutability. Cheers, Sven

On 2012-02-24, at 9:29 PM, Victor Stinner wrote:
-1 on this. The next move would be adding friend classes and protected methods ;) __setattr__ works perfectly for those purposes. Moreover, you can emulate your idea on unpatched python by using metaclasses. - Yury

Ned Batchelder wrote:
That is silly. That alleged "Python answer" is like telling people that they don't need test frameworks or debuggers because the "Python answer" for people wanting to debug their code is not to write buggy code in the first place. Python has read-only data structures: tuple, frozenset, str, etc. If you ask yourself why Python has immutable types, it might give you a clue why Victor wants the ability to create other immutable types like frozendict, and why "don't modify them" is not a good enough answer: - Immutable types can be used as keys in dicts. - Immutable types protect you from errors. While you might intend not to modify a data structure, bugs do happen. Immutability gives you an immediate exception at the exact time and place you attempt to modify the data structure instead of at some arbitrary time later far from the actual bug. Python has excellent support for read-only data structures, so long as you write them in C. -- Steven

On 2012-02-26, at 00:05 , Steven D'Aprano wrote:
- Immutable types can be used as keys in dicts.
*technically*, you can use mutable types as dict keys if you define their __hash__ no? That is of course a bad idea when the instances are *expected* to be modified, but it should "work".
- Immutable types protect you from errors. While you might intend not to modify a data structure, bugs do happen.
Immutables are also inherently thread-safe (since thread safety is about shared state, and shared immutables are not state). Which is a nice guarantee.
Python has excellent support for read-only data structures, so long as you write them in C.
There's also good support of the "consenting adults" variety (use _-prefixed attributes for the actual state and expose what needs to be exposed via properties and methods). That can be simplified with a custom descriptor type which can only be set once (similar to java's `final`), it would be set in the type's constructor and never re-set from this.

On Feb 26, 2012 1:35 AM, "Masklinn" <masklinn@masklinn.net> wrote:
I wouldn't say this is necessarily a bad thing at all. It just depends what defines the object. If an instance represent a specific object (e.g. a database record) you wouldn't expect the hash to change if you modified an attribute of it, since the instance still represents the same object.
you write them in C.
Maybe I'm missing something here, but what's wrong with just using __getattr__, __setattr__ and __delattr__ to restrict access?

On Sat, Feb 25, 2012 at 6:32 PM, Masklinn <masklinn@masklinn.net> wrote:
On 2012-02-26, at 00:05 , Steven D'Aprano wrote:
- Immutable types can be used as keys in dicts.
Not always; for example, you can't use a tuple of lists, even though the tuple itself is immutable.
Not even a bad idea, if you define the hash carefully. (Similar to java final.) Once hash(obj) returns something other than -1, it should return that same value forever. Attributes which do not contribute to the hash can certainly still change. That said, I would be nervous about changes to attributes that contribute to __eq__, just because third party code may be so surprised.
-jJ

An easy way to create immutable instances is 'collections.namedtuple': X = namedtuple("X", "a b") x = X(a=4, b=2) x.a + x.b # fine x.a = 5 # AttributeError: can't set attribute x.c = 5 # AttributeError: 'X' object has no attribute 'c' Tricks using 'object.__setattr__()' etc. will fail since the instance doesn't have a '__dict__'. The only data in the instance is stored in a tuple, so it's as immutable as a tuple. You can also derive from 'X' to add further methods. Remember to set '__slots__' to an empty iterable to maintain immutability. Cheers, Sven
participants (8)
-
David Townshend
-
Jim Jewett
-
Masklinn
-
Ned Batchelder
-
Steven D'Aprano
-
Sven Marnach
-
Victor Stinner
-
Yury Selivanov