[Python-ideas] Should Python have user-defined constants?

Chris Angelico rosuav at gmail.com
Tue Nov 21 19:47:28 EST 2017

On Wed, Nov 22, 2017 at 11:27 AM, Steven D'Aprano <steve at pearwood.info> wrote:
> On Tue, Nov 21, 2017 at 09:34:33AM -0800, Chris Barker wrote:
>> On Tue, Nov 21, 2017 at 3:31 AM, Steven D'Aprano <steve at pearwood.info>
>> wrote:
>> >  The
>> > interesting (but is it useful?) concept is constant identifiers which
>> > cannot be re-bound or re-assigned once they are set the first time.
>> This would actually be a substantial shift in what Python is about --
>> currently the concept of type is all about values, not names
> I didn't say anything about types. My comments were about names and
> values (objects):
> - Mutability is a property of values (objects): some objects are
>   mutable, and other objects are not.
> - Constantness is a property of names or other identifiers: some
>   names can only be bound once ("constants"), other names can be
>   bound and rebound at will ("variables").
> Types are literally irrelevant to this, except in the sense that in many
> languages, including Python, the distinction between mutable and
> immutable is usually controlled by the type of object. But that's not
> fundamental to the concept: we could, if we wanted, decouple the two.

There's a good reason for that - the type of an object determines what
operations make sense (you can add two numbers together, but you can't
add two open sockets), and mutability impacts the validity of
operations. Can you give an example of where it would make sense to
decouple mutability from object type? Everything I can think of in
Python works by creating a separate type (eg frozenset for set), thus
allowing new operations (eg hashing). The only way I can think of to
decouple them would be to have a single type with all the operations
available, and then raise exceptions where some operations aren't

class Foo:
    def __hash__(self):
        if self.mutable: raise TypeError
        return some_hash
    def __iadd__(self, other):
        if not self.mutable: return self + other
        # perform an in-place addition
        return self
    def __setitem__(self, key):
        if not self.mutable: raise TypeError
        # alter self

This makes it hard to reason about the code - particularly in the case
of __iadd__, where it'll sometimes behave like a list's += and
sometimes like an int's. Where would you, preferably with some sort of
real-world example, actually make use of this sort of thing?


More information about the Python-ideas mailing list