473,385 Members | 1,372 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,385 software developers and data experts.

Making immutable instances

Howdy all,

How can a (user-defined) class ensure that its instances are
immutable, like an int or a tuple, without inheriting from those
types?

What caveats should be observed in making immutable instances?

--
\ "Love is the triumph of imagination over intelligence." -- |
`\ Henry L. Mencken |
_o__) |
Ben Finney
Nov 23 '05
90 4283
On Thu, 24 Nov 2005 11:44:16 -0500, Mike Meyer wrote:
In Python, I can even fix
it so *your* code uses my wrapped version:

import Finney
class Addable(Finnney.Immutable): pass
Finney.Immutable = Addable

Which means that from now on *your* code that tries to create
Immutables will actually get Addables. The inability to do this in B&D
languages is - well, painfull. That Python doesns't require the
boilerplate in a good thing.


The ability to shoot yourself in the foot *if you want to* is a feature,
not a bug. But the ability to shoot yourself in the foot *accidentally* is
not a feature.

I am happy that whatever restrictions the class designer builds on their
class is easy to bypass, because the class designer is not omniscient
and their "private data" may be just the thing I need to solve a
problem some day. But I should have to *think about it* before messing
about with it.

Python's consenting adults philosophy allows the class designer some
limited ability to force the class user to think about it before messing
about with private variables. I think Ben's immutable class falls into
that same category.
--
Steven.

Nov 26 '05 #51
Steven D'Aprano <st***@REMOVETHIScyber.com.au> writes:
On Thu, 24 Nov 2005 11:44:16 -0500, Mike Meyer wrote:
In Python, I can even fix
it so *your* code uses my wrapped version:

import Finney
class Addable(Finnney.Immutable): pass
Finney.Immutable = Addable


Python's consenting adults philosophy allows the class designer some
limited ability to force the class user to think about it before messing
about with private variables. I think Ben's immutable class falls into
that same category.


If you read the whole thread, you'll see that I don't have a problem
with messing with private variables. It's disallowing the addition of
new variables that I found objectionable.

<mike
--
Mike Meyer <mw*@mired.org> http://www.mired.org/home/mwm/
Independent WWW/Perforce/FreeBSD/Unix consultant, email for more information.
Nov 26 '05 #52
On Fri, 25 Nov 2005 20:50:41 -0500, Mike Meyer wrote:
Steven D'Aprano <st***@REMOVETHIScyber.com.au> writes:
On Thu, 24 Nov 2005 11:44:16 -0500, Mike Meyer wrote:
In Python, I can even fix
it so *your* code uses my wrapped version:

import Finney
class Addable(Finnney.Immutable): pass
Finney.Immutable = Addable


Python's consenting adults philosophy allows the class designer some
limited ability to force the class user to think about it before messing
about with private variables. I think Ben's immutable class falls into
that same category.


If you read the whole thread, you'll see that I don't have a problem
with messing with private variables. It's disallowing the addition of
new variables that I found objectionable.


But you've just demonstrated that those who really want to shoot
themselves in the foot, er, add new attributes (not variables, let's get
the terminology right) can do so by sub-classing and rebinding. The fact
that Ben's proposal would prevent you from adding attributes is precisely
analogous to the name mangling that Python does: if you want to work
around it, it is easy to do so, but you have to make a conscious effort to
do so it.

"Hmmm, the class designer didn't want me adding attributes to instances...
maybe he had a good reason for that..."
--
Steven.

Nov 26 '05 #53
Steven D'Aprano <st***@REMOVETHIScyber.com.au> writes:
"Hmmm, the class designer didn't want me adding attributes to instances...
maybe he had a good reason for that..."


When it was suggested that a facility for doing this be added to the
language, I asked for a use case for it. Nobodies come up with a
reason for placing such restriction on the client yet. If you've got a
use case, I'd be interested in hearing it.

<mike
--
Mike Meyer <mw*@mired.org> http://www.mired.org/home/mwm/
Independent WWW/Perforce/FreeBSD/Unix consultant, email for more information.
Nov 26 '05 #54
On Fri, 25 Nov 2005 23:20:05 -0500, Mike Meyer wrote:
Steven D'Aprano <st***@REMOVETHIScyber.com.au> writes:
"Hmmm, the class designer didn't want me adding attributes to instances...
maybe he had a good reason for that..."
When it was suggested that a facility for doing this be added to the
language, I asked for a use case for it. Nobodies come up with a
reason for placing such restriction on the client yet.


Oh, I think it is terribly unfair to call them nobodies, even if you don't
like their use-cases *grin*
If you've got a use case, I'd be interested in hearing it.


frozenset perhaps? If it were needed once, it could be needed again.

The obvious case would be for a class where distinct instances that
compare equal but not identical map to the same value in a dict.

In any case, I'm not the one claiming that I need custom immutable
classes. I'm just suggesting that there is nothing non-Pythonic about
them. If Ben thinks he needs them, I'm sure he has put *far* more thought
into it than I have. I know Ben in RL, and he is not someone to make snap
judgements about turning Python into Some Other Language Just Because.
--
Steven.

Nov 26 '05 #55
Steven D'Aprano <st***@REMOVETHIScyber.com.au> writes:
On Fri, 25 Nov 2005 23:20:05 -0500, Mike Meyer wrote:
If you've got a use case, I'd be interested in hearing it. frozenset perhaps? If it were needed once, it could be needed again.


That's not a use case, that's an example. And not a very good one, as
it's not at all clear that the restriction is intentional in that
case. After all, the same restriction applies to every builtin type,
including the mutable version of frozenset.
The obvious case would be for a class where distinct instances that
compare equal but not identical map to the same value in a dict.
How does the ability to add attributes to the instances of the class
change that behavior?
In any case, I'm not the one claiming that I need custom immutable
classes. I'm just suggesting that there is nothing non-Pythonic about
them. If Ben thinks he needs them, I'm sure he has put *far* more thought
into it than I have. I know Ben in RL, and he is not someone to make snap
judgements about turning Python into Some Other Language Just Because.


I claim that the dynamic natture of Python - which is exemplified by
things like duck typing and the ability to add attributes to nearly
everything on the fly - is a fundamental part of what makes Python
Python. The best reason Ben could come up with is that it makes
finding bugs a bit easier. But so do type declarations, static
namespaces, private and protected attributes, and a slew of similar
B&D features that are pretty much anathema to dynamic languages. This
feature fits *very* well in languages that have those features, and
poorly in languages that reject them, which includes Python.

Of course, that a feature has a lot in common with features from
un-Pythonic languages doesn't make it ipso facto unPythonic. After
all, practicality beats purity. So what's the practical application
for such a feature? What's the use case?

<mike
--
Mike Meyer <mw*@mired.org> http://www.mired.org/home/mwm/
Independent WWW/Perforce/FreeBSD/Unix consultant, email for more information.
Nov 26 '05 #56
On Sat, 26 Nov 2005 04:59:59 -0500, Mike Meyer wrote:
Steven D'Aprano <st***@REMOVETHIScyber.com.au> writes:
On Fri, 25 Nov 2005 23:20:05 -0500, Mike Meyer wrote:
If you've got a use case, I'd be interested in hearing it. frozenset perhaps? If it were needed once, it could be needed again.


That's not a use case, that's an example.


Fine. "I want to use a set as a dictionary key, but dict keys must be
immutable."

And not a very good one, as
it's not at all clear that the restriction is intentional in that
case. After all, the same restriction applies to every builtin type,
including the mutable version of frozenset.
Every builtin type, including mutable sets, is immutable???

I think we're talking at cross purposes. I'm talking about immutable
instances. What are you talking about?

The obvious case would be for a class where distinct instances that
compare equal but not identical map to the same value in a dict.


How does the ability to add attributes to the instances of the class
change that behavior?


Er, who said it did?

In any case, I'm not the one claiming that I need custom immutable
classes. I'm just suggesting that there is nothing non-Pythonic about
them. If Ben thinks he needs them, I'm sure he has put *far* more thought
into it than I have. I know Ben in RL, and he is not someone to make snap
judgements about turning Python into Some Other Language Just Because.


I claim that the dynamic natture of Python - which is exemplified by
things like duck typing and the ability to add attributes to nearly
everything on the fly - is a fundamental part of what makes Python
Python.


I can't disagree with you there.
The best reason Ben could come up with is that it makes
finding bugs a bit easier.
Are you sure that was Ben? Maybe I missed it.

But so do type declarations, static
namespaces, private and protected attributes, and a slew of similar
B&D features that are pretty much anathema to dynamic languages. This
feature fits *very* well in languages that have those features, and
poorly in languages that reject them, which includes Python.
Perhaps. But I don't object to *mild* B&D, the sort you can get out of
relatively easily. You know, handcuffs, maybe a few ropes, but not
lock-them-up-in-the-oubliette-and-throw-away-the-key *wink*

All joking aside, I think having immutable custom classes, with or without
restricting attribute creation, is no worse than (say) Python's name
mangling.

Of course, that a feature has a lot in common with features from
un-Pythonic languages doesn't make it ipso facto unPythonic. After
all, practicality beats purity. So what's the practical application
for such a feature? What's the use case?


Class instances match by identity when used as keys, not equality. That's
over-strict: why should Parrot("Norwegian Blue") map to a different item
from Parrot("Norwegian" + " Blue") just because the first instance has a
different memory location to the second?

Please note, I do not expect -- and would not want -- the default
behaviour to change. Most class instances presumably should be mutable,
and therefore mapping by ID is the right behaviour.

But some class instances shouldn't be mutable, and should match as keys by
equality not identity: we would expect Fraction(num=1, den=2) to match
Fraction(num=2, den=4) as a key.

--
Steven.

Nov 26 '05 #57
Steven D'Aprano <st***@REMOVETHIScyber.com.au> writes:
On Sat, 26 Nov 2005 04:59:59 -0500, Mike Meyer wrote:
Steven D'Aprano <st***@REMOVETHIScyber.com.au> writes:
On Fri, 25 Nov 2005 23:20:05 -0500, Mike Meyer wrote:
If you've got a use case, I'd be interested in hearing it.
frozenset perhaps? If it were needed once, it could be needed again. That's not a use case, that's an example.

Fine. "I want to use a set as a dictionary key, but dict keys must be
immutable."


Except that dict keys don't have to be immutable. The docs say (or
imply) that, but they're wrong. We're discussing new wording in
another thread.
And not a very good one, as
it's not at all clear that the restriction is intentional in that
case. After all, the same restriction applies to every builtin type,
including the mutable version of frozenset.

Every builtin type, including mutable sets, is immutable???


No. I think you missed the entire second half the thread.
I think we're talking at cross purposes. I'm talking about immutable
instances. What are you talking about?
I'm talking about being able to add attributes to an instance. You
can't add an attribute to *any* builtin type. This is an
implementation detail. I consider it to be a wart in the language, but
an acceptable one, because the costs of fixing it are much worse than
the costs of working around it, and practicality beats purity.
The obvious case would be for a class where distinct instances that
compare equal but not identical map to the same value in a dict.

How does the ability to add attributes to the instances of the class
change that behavior?

Er, who said it did?


You did. We're looking for a use case for adding the ability to mark a
class as having instances that you can't add an attribute to. You
suggested this as such a use case.
The best reason Ben could come up with is that it makes
finding bugs a bit easier.

Are you sure that was Ben? Maybe I missed it.


No, I'm no sure it was Ben - I didn't go chase down the
reference. It's the best use case *from anyone* so far, though.
All joking aside, I think having immutable custom classes, with or without
restricting attribute creation, is no worse than (say) Python's name
mangling.
There are well-defined facilities for creating read-only
attributes. Is there a difference between an immutable object you can
add attributes to, and an object that has nothing but read-only
attributes?
Of course, that a feature has a lot in common with features from
un-Pythonic languages doesn't make it ipso facto unPythonic. After
all, practicality beats purity. So what's the practical application
for such a feature? What's the use case?

Class instances match by identity when used as keys, not equality. That's
over-strict: why should Parrot("Norwegian Blue") map to a different item
from Parrot("Norwegian" + " Blue") just because the first instance has a
different memory location to the second?


Uh - HTH did we get here?
Please note, I do not expect -- and would not want -- the default
behaviour to change. Most class instances presumably should be mutable,
and therefore mapping by ID is the right behaviour.
The default behavior is right for in many cases. For those that it's
not right, you can fix it. Proper definition of the Parrot class will
insure that Parrot("Norwegian Blue") == Parrot("Norwegian" + " Blue")
always evaluates to True.
But some class instances shouldn't be mutable, and should match as keys by
equality not identity: we would expect Fraction(num=1, den=2) to match
Fraction(num=2, den=4) as a key.


And you can do that with Python as it exists today (and one of these
days I'll get back to my Rational class that does that...). There's no
need for any changes to the language to deal with this case.

<mike
--
Mike Meyer <mw*@mired.org> http://www.mired.org/home/mwm/
Independent WWW/Perforce/FreeBSD/Unix consultant, email for more information.
Nov 26 '05 #58
Op 2005-11-26, Steven D'Aprano schreef <st***@REMOVETHIScyber.com.au>:
On Thu, 24 Nov 2005 12:55:07 +0000, Antoon Pardon wrote:
Suppose I have the following code.

from module import __take_care__

__private_detail__ = ...

I now have two variable that are flaged the same way, but they are not.
No, you have two names written using a poor naming convention.


Well if it is a poor naming convention, why react to me, and not to
Mike who was defending this poor naming convention?
__name__ should be used only for Python's special methods.
__take_care__ is a private variable from an other module which I should
use with extreme care not to break the other package.


Python doesn't do any special treatment of __name or __name__ from
modules. The only information hiding techniques Python enforces are that
module._name (single leading underscore) is not imported by "from module
import *", and class.__name (double leading underscore) is mangled to
class._Class__name.


We were not talkin about special treatment by python. We were talking
about conventions to communicate purpose to other readers of the
software.
It are other modules that should take special care if they
should choose to import this variable.


I'm not sure what the difference is. If there is a difference, why are you
using the same naming convention for different sorts of names ("private
module variable" and "private module data"). If there is no difference, I
don't understand the point of your example.


Well it seems you didn't seem to understand the point of my answer.
Maybe you should first reread the article I responded too.

--
Antoon Pardon
Nov 28 '05 #59
Mike Meyer <mw*@mired.org> writes:
When it was suggested that a facility for doing this be added to the
language, I asked for a use case for it. Nobodies come up with a
reason for placing such restriction on the client yet. If you've got a
use case, I'd be interested in hearing it.


I see it the other way; almost all the time in my own code I try to
initialize all of any instance's attributes in an __init__ method.
Dynamically adding attributes is useful sometimes, but done
willy-nilly leads to spaghetti code. In the cases where it's useful,
I'd rather see it done through a special __setattr__ method, perhaps
inherited from a mixin:

class Frob(Whatsit, DynamicAttributeMixin):
...

However, that's not likely to happen.
Nov 30 '05 #60
Paul Rubin <http://ph****@NOSPAM.invalid> writes:
Mike Meyer <mw*@mired.org> writes:
When it was suggested that a facility for doing this be added to the
language, I asked for a use case for it. Nobodies come up with a
reason for placing such restriction on the client yet. If you've got a
use case, I'd be interested in hearing it. I see it the other way; almost all the time in my own code I try to
initialize all of any instance's attributes in an __init__ method.
Dynamically adding attributes is useful sometimes, but done
willy-nilly leads to spaghetti code.


Pretty much anything, if abused, can lead to "spaghetti code".
In the cases where it's useful,
I'd rather see it done through a special __setattr__ method, perhaps
inherited from a mixin:

class Frob(Whatsit, DynamicAttributeMixin):
...

However, that's not likely to happen.


The thing is, the need for an extra attribute doesn't come from your
class, it comes from the client of your class. You can't know if the
client code will need that facility or not, so the only choice you
know won't be wrong sometime is to always add the mixin. In which
case, you should follow the Python "the less boilerplate, the better"
practice, and leave it off. Which is what we have.

Letting the class author declare whether or not the client can add
attributes is wrong for the same reasons - and in the same places -
that letting the class author declare that the client shouldn't be
allowed to access specific attributes, and so on, is wrong. Of
course, it's also *right* for the same reasons and in the same places
as those things. I just don't think those places happen in Python
programs.

<mike
--
Mike Meyer <mw*@mired.org> http://www.mired.org/home/mwm/
Independent WWW/Perforce/FreeBSD/Unix consultant, email for more information.
Nov 30 '05 #61
Mike Meyer <mw*@mired.org> writes:
Letting the class author declare whether or not the client can add
attributes is wrong for the same reasons - and in the same places -
that letting the class author declare that the client shouldn't be
allowed to access specific attributes, and so on, is wrong.


The same logic can apply to what the class operations should do. The
answer is the same in both cases. That's why subclassing and
inheritance were invented.
Nov 30 '05 #62

Mike Meyer wrote:
The thing is, the need for an extra attribute doesn't come from your
class, it comes from the client of your class. You can't know if the
client code will need that facility or not, so the only choice you
know won't be wrong sometime is to always add the mixin. In which
case, you should follow the Python "the less boilerplate, the better"
practice, and leave it off. Which is what we have.

Letting the class author declare whether or not the client can add
attributes is wrong for the same reasons - and in the same places -
that letting the class author declare that the client shouldn't be
allowed to access specific attributes, and so on, is wrong. Of
course, it's also *right* for the same reasons and in the same places
as those things. I just don't think those places happen in Python
programs.

I am puzzled, and could have read what you want wrong. Are you saying
you want something like this :

a={}
a.something = "I want to hang my stuff here, outside the intended use
of dict"

Nov 30 '05 #63
Paul Rubin <http://ph****@NOSPAM.invalid> writes:
Mike Meyer <mw*@mired.org> writes:
Letting the class author declare whether or not the client can add
attributes is wrong for the same reasons - and in the same places -
that letting the class author declare that the client shouldn't be
allowed to access specific attributes, and so on, is wrong.

The same logic can apply to what the class operations should do. The
answer is the same in both cases. That's why subclassing and
inheritance were invented.


Exactly. Adding an attribute is isomorphic to subclassing, except it
doesn't' take any boilerplate. Unless you do something to prevent
people from subclassing, they can always write the boilerplate and
pretty much continue as before. I don't believe there's a good reason
for preventing the boilerplate free method, and repeated requests for
a use case for this have gone unsatisied.

Have you got a use case?

<mike
--
Mike Meyer <mw*@mired.org> http://www.mired.org/home/mwm/
Independent WWW/Perforce/FreeBSD/Unix consultant, email for more information.
Nov 30 '05 #64
bo****@gmail.com writes:
I am puzzled, and could have read what you want wrong. Are you saying
you want something like this :

a={}
a.something = "I want to hang my stuff here, outside the intended use
of dict"


Exactly. For a use case, consider calling select.select on lists of
file objects. If the processing is simple enough, the clearest way to
associate a handler with each socket is just to add it as an
attribute. But that doesn't work - sockets are bulitin types. So you
consider less light-weight solutions, like subclassing socket (now
that that's possible), or a dictionary of handlers keyed by socket.

This works by default with classes written in Python. That it doesn't
work for builtins is inconsistent, non-orthogonal, and
incomplete. However, it's easy to work around, and the obvious fix -
adding a dictionary to every builtin - is rather costly. So we'll live
with it since practicality beats purity.

<mike
--
Mike Meyer <mw*@mired.org> http://www.mired.org/home/mwm/
Independent WWW/Perforce/FreeBSD/Unix consultant, email for more information.
Nov 30 '05 #65

Mike Meyer wrote:
bo****@gmail.com writes:
I am puzzled, and could have read what you want wrong. Are you saying
you want something like this :

a={}
a.something = "I want to hang my stuff here, outside the intended use
of dict"


Exactly. For a use case, consider calling select.select on lists of
file objects. If the processing is simple enough, the clearest way to
associate a handler with each socket is just to add it as an
attribute. But that doesn't work - sockets are bulitin types. So you
consider less light-weight solutions, like subclassing socket (now
that that's possible), or a dictionary of handlers keyed by socket.

This works by default with classes written in Python. That it doesn't
work for builtins is inconsistent, non-orthogonal, and
incomplete. However, it's easy to work around, and the obvious fix -
adding a dictionary to every builtin - is rather costly. So we'll live
with it since practicality beats purity.

While I agree with the use case(I want it sometimes too), it seems that
the language creator may also deliberately disallow that, not because
it is not doable or costly. So how, the built-in types still need to
have some form of dictionary or else how would dir(a) of the above
dictionary work ?

Dec 1 '05 #66
bo****@gmail.com writes:
Mike Meyer wrote:
bo****@gmail.com writes:
> I am puzzled, and could have read what you want wrong. Are you saying
> you want something like this :
> a={}
> a.something = "I want to hang my stuff here, outside the intended use
> of dict"

Exactly. For a use case, consider calling select.select on lists of
file objects. If the processing is simple enough, the clearest way to
associate a handler with each socket is just to add it as an
attribute. But that doesn't work - sockets are bulitin types. So you
consider less light-weight solutions, like subclassing socket (now
that that's possible), or a dictionary of handlers keyed by socket.
This works by default with classes written in Python. That it doesn't
work for builtins is inconsistent, non-orthogonal, and
incomplete. However, it's easy to work around, and the obvious fix -
adding a dictionary to every builtin - is rather costly. So we'll live
with it since practicality beats purity.

While I agree with the use case(I want it sometimes too), it seems that
the language creator may also deliberately disallow that, not because
it is not doable or costly. So how, the built-in types still need to
have some form of dictionary or else how would dir(a) of the above
dictionary work ?


Built-in types don't have a real dictionary. They have a C struct that
holds the various methods. The entries in the struct are called
"slots", hence the __slots__ magic attribute. That __slots__ makes it
impossible to add an attribute is documented as an implementation
detail. This makes me think that the same restriction on the builtin
types is the same.

FWIW, dir returns a list built from a number of source. But if you
look at, for example, list.__dict__, you'll notice that it's not a
dict.

<mike
--
Mike Meyer <mw*@mired.org> http://www.mired.org/home/mwm/
Independent WWW/Perforce/FreeBSD/Unix consultant, email for more information.
Dec 1 '05 #67

Mike Meyer wrote:
Built-in types don't have a real dictionary. They have a C struct that
holds the various methods. The entries in the struct are called
"slots", hence the __slots__ magic attribute. That __slots__ makes it
impossible to add an attribute is documented as an implementation
detail. This makes me think that the same restriction on the builtin
types is the same.

FWIW, dir returns a list built from a number of source. But if you
look at, for example, list.__dict__, you'll notice that it's not a
dict.

Well, in this case, would it be simple for the OP that if he wants to
disallow this attaching additional things, just use __slot__.

What I wan to say though is, if we can live with the inability of not
able to attach to built-in types, why is it so difficult for other user
defined class ? If the authors go to the length of not allowing it, so
be it. They are afterall define it for their use and how someone else
will use it don't matter.

Dec 1 '05 #68
bo****@gmail.com writes:
Well, in this case, would it be simple for the OP that if he wants to
disallow this attaching additional things, just use __slot__.
That's *documented* as an implementation-dependent behavior. Using it
to get that effect is abuse of the feature, and may well quit working
in the future.
What I wan to say though is, if we can live with the inability of not
able to attach to built-in types, why is it so difficult for other user
defined class ?
Because not being able to do it for built-in types is an
implementation detail, and a wart in the language.

And again, *what's the use case*? A number of people have asked why we
shouldn't allow this, but none of them been able to come up with a use
case better than "I think doing that is bad style."
If the authors go to the length of not allowing it, so be it. They
are afterall define it for their use and how someone else will use
it don't matter.


I take it you never distribute your code, or otherwise expect other
people to reuse it?

<mike
--
Mike Meyer <mw*@mired.org> http://www.mired.org/home/mwm/
Independent WWW/Perforce/FreeBSD/Unix consultant, email for more information.
Dec 1 '05 #69

Mike Meyer wrote:
If the authors go to the length of not allowing it, so be it. They
are afterall define it for their use and how someone else will use
it don't matter.


I take it you never distribute your code, or otherwise expect other
people to reuse it?

No, distribute when necessary. But I define it and code it the way I
want, how and others will use it, curse it doesn't matter to me.

Of course, I would give suggestion(wish list bug as in debian term)
when I use other people's stuff, and see a particular usage that is not
there. But it ends just there, wish list.

Dec 1 '05 #70

Mike Meyer wrote:
bo****@gmail.com writes:
Well, in this case, would it be simple for the OP that if he wants to
disallow this attaching additional things, just use __slot__.


That's *documented* as an implementation-dependent behavior. Using it
to get that effect is abuse of the feature, and may well quit working
in the future.

In this case, it seems to be fine. As the intend is just "not
allowing". Even it changes in the future, the worst case is just
"allowing", that fits your needs :-)

It still won't affect what is working, so it is harmless side effect,
if it ever changes in the future.

Abuse or not doesn't matter so long it fits the needs, IMO.

Dec 1 '05 #71

Mike Meyer wrote:
bo****@gmail.com writes:
Well, in this case, would it be simple for the OP that if he wants to
disallow this attaching additional things, just use __slot__.


That's *documented* as an implementation-dependent behavior. Using it
to get that effect is abuse of the feature, and may well quit working
in the future.

I don't see it mention as implementation-dependent behaviour on this
page, and this is supposed to be "(for language lawyers)".

http://www.python.org/doc/2.4.2/ref/slots.html

If it really is implementation detail but not a binding to the language
feature, I think someone need to change the doc, at least make it more
clear on this page.

Dec 1 '05 #72

Mike Meyer wrote:
And again, *what's the use case*? A number of people have asked why we
shouldn't allow this, but none of them been able to come up with a use
case better than "I think doing that is bad style."

oh, that is the usual argument anyway. It is nothing but style, most of
the time. Making a style thing into a right/wrong, better/worse
argument is really for time killing, there would never be real answer.

Dec 1 '05 #73
bo****@gmail.com writes:
Mike Meyer wrote:
bo****@gmail.com writes:
> Well, in this case, would it be simple for the OP that if he wants to
> disallow this attaching additional things, just use __slot__. That's *documented* as an implementation-dependent behavior. Using it
to get that effect is abuse of the feature, and may well quit working
in the future.

It still won't affect what is working, so it is harmless side effect,
if it ever changes in the future.


If not allowing is required, then allowing is "not working", pretty
much by definition.
Abuse or not doesn't matter so long it fits the needs, IMO.


I guess it doesn't matter to you whether or not your code works in the
future. It does to me.

<mike
--
Mike Meyer <mw*@mired.org> http://www.mired.org/home/mwm/
Independent WWW/Perforce/FreeBSD/Unix consultant, email for more information.
Dec 1 '05 #74

Mike Meyer wrote:
bo****@gmail.com writes:
Mike Meyer wrote:
bo****@gmail.com writes:
> Well, in this case, would it be simple for the OP that if he wants to
> disallow this attaching additional things, just use __slot__.
That's *documented* as an implementation-dependent behavior. Using it
to get that effect is abuse of the feature, and may well quit working
in the future.

It still won't affect what is working, so it is harmless side effect,
if it ever changes in the future.


If not allowing is required, then allowing is "not working", pretty
much by definition.
Abuse or not doesn't matter so long it fits the needs, IMO.


I guess it doesn't matter to you whether or not your code works in the
future. It does to me.

For this particular case, I don't see it as a problem.

First it meets the need, works on 2.2, 2.3, 2.4. No one knows what
would change in the future, beside the fact that I don't see it as
implementation-dependent in the doc.

Adding to the fact that things can/may be removed even it is fully
documented, without this caveat emptor(like the famous reduce/map
etc.). That is if I read the document when I was writing python codes
in the early days and used reduce/map/filter/lambda, my code still
breaks if in one day those are removed and I can't forsee that either.

So why bother, unless it has some definitive schedule(like saying in
2.5, reduce won't be there or __slot__ behaviour will definitely
change), then I would consider if the code I write now should avoid
using it.

And back to this case, I regard it as a no harm side effect, yes, it
doesn't perform as expected(assume it really is changed in some unknown
version in the future) that someone does hang something there, it
doesn't hurt my expected usage of the class, as this is used to prevent
unexpected usage.

Quoting the frequently used term "Practicality beats purity". If I have
a practical problem/needs now and it solves it, why not use it ?

The zip(it,it) case is even worse than this __slot__ situation and I
don't have much problem in using that either. It is not unusual in this
industry that certain software only expects to be working with some
combination of OS/Compiler version.

Dec 1 '05 #75
bo****@gmail.com writes:
Quoting the frequently used term "Practicality beats purity". If I have
a practical problem/needs now and it solves it, why not use it ?


In other words, you have a use case. Cool. Please tell us what it is -
at least if it's better than "I think that's bad style."

<mike
--
Mike Meyer <mw*@mired.org> http://www.mired.org/home/mwm/
Independent WWW/Perforce/FreeBSD/Unix consultant, email for more information.
Dec 1 '05 #76

Mike Meyer wrote:
bo****@gmail.com writes:
Quoting the frequently used term "Practicality beats purity". If I have
a practical problem/needs now and it solves it, why not use it ?


In other words, you have a use case. Cool. Please tell us what it is -
at least if it's better than "I think that's bad style."

Huh ? I said that if I need "immutable instance", I won't hestiate to
use __slot__, I didn't say I have a need.

In other words, I see __slot__ as a solution to the problem, I am not
saying I have the problem in the first place. The "practicabilty beats
purity" is used to support this using __slot__ situation, not about the
need of immutable instance.

Dec 1 '05 #77
bo****@gmail.com writes:
Mike Meyer wrote:
bo****@gmail.com writes:
> Quoting the frequently used term "Practicality beats purity". If I have
> a practical problem/needs now and it solves it, why not use it ?

In other words, you have a use case. Cool. Please tell us what it is -
at least if it's better than "I think that's bad style."

Huh ? I said that if I need "immutable instance", I won't hestiate to
use __slot__, I didn't say I have a need.


A need implies a use case. Yes, you didn't say you had one, you said
if, and I jumpted the gun.

Lots of people seem to want immutable instances. Nobody seems to have
a use case for them.

<mike
--
Mike Meyer <mw*@mired.org> http://www.mired.org/home/mwm/
Independent WWW/Perforce/FreeBSD/Unix consultant, email for more information.
Dec 1 '05 #78
Mike Meyer <mw*@mired.org> writes:
Lots of people seem to want immutable instances. Nobody seems to have
a use case for them.


What is the use case for immutable strings? Why shouldn't strings be
mutable like they are in Scheme?

Generally if I know I don't plan to mutate something, I'd want to make
it immutable so the runtime system can notice if I make an error.
It's like an "assert" statement spread through the whole program.
Dec 1 '05 #79
Mike Meyer <mw*@mired.org> wrote:
Lots of people seem to want immutable instances. Nobody seems to
have a use case for them.


Perhaps you missed my release announcement of the 'enum' package that
explains why Enum instances are immutable.

--
\ "Hanging one scoundrel, it appears, does not deter the next. |
`\ Well, what of it? The first one is at least disposed of." -- |
_o__) Henry L. Mencken |
Ben Finney
Dec 1 '05 #80
Paul Rubin <http://ph****@NOSPAM.invalid> writes:
Mike Meyer <mw*@mired.org> writes:
Lots of people seem to want immutable instances. Nobody seems to have
a use case for them. What is the use case for immutable strings? Why shouldn't strings be
mutable like they are in Scheme?


I don't know. Why shouldn't they?
Generally if I know I don't plan to mutate something, I'd want to make
it immutable so the runtime system can notice if I make an error.
It's like an "assert" statement spread through the whole program.


That's not a use case, that's a debugging aid. The same logic applies
to adding type declarations, private/public/etc. declerations, and
similar B&D language features. It's generally considered that it's not
a good enough reason for adding those, so it doesn't really constitute
a good enough reason for making an instance immutable.

<mike
--
Mike Meyer <mw*@mired.org> http://www.mired.org/home/mwm/
Independent WWW/Perforce/FreeBSD/Unix consultant, email for more information.
Dec 2 '05 #81
Ben Finney <bi****************@benfinney.id.au> writes:
Mike Meyer <mw*@mired.org> wrote:
Lots of people seem to want immutable instances. Nobody seems to
have a use case for them.

Perhaps you missed my release announcement of the 'enum' package that
explains why Enum instances are immutable.


Yes, I did. I couldn't turn it up in Google, either. I did find a long
thread where you discuss the issue. Reading that, I found
justifications for having a constant hash value, and having immutable
attributes - but I've known about those for a long time.. Neither of
these constitutes an immutable instance.

Could I get you to recap the reason?

thanks,
<mike
--
Mike Meyer <mw*@mired.org> http://www.mired.org/home/mwm/
Independent WWW/Perforce/FreeBSD/Unix consultant, email for more information.
Dec 2 '05 #82

Mike Meyer wrote:
That's not a use case, that's a debugging aid. The same logic applies
to adding type declarations, private/public/etc. declerations, and
similar B&D language features. It's generally considered that it's not
a good enough reason for adding those, so it doesn't really constitute
a good enough reason for making an instance immutable.

By design, this is a "don't use" feature so it would be very hard to
find a "use case" ;-)

I can only think of a situation which may not be able to detect by
testing. Say I have a module version 1 which is used by app version 1.

In your app, you attach your own attribute to an instance of the
module. Everything is fine. Now module becomes version 2 which happens
to use the same attribute name that you hang on it and the program
starts to behave strangely because they are stepping on each other's
foot without knowing it. If everything is done by the same group of
people with good communication, it may be possible to detect it. But if
the module is done by a third party, and the app is done by yet another
third party. The situation becomes complicated. Say if under debian, I
do an apt-get python-sqlobject which may be used by multiple apps. If
one of them happens to do it this way, this senario may happen.

Dec 2 '05 #83
Mike Meyer <mw*@mired.org> wrote:
Ben Finney <bi****************@benfinney.id.au> writes:
Mike Meyer <mw*@mired.org> wrote:
Lots of people seem to want immutable instances. Nobody seems to
have a use case for them. Perhaps you missed my release announcement of the 'enum' package
that explains why Enum instances are immutable.


Yes, I did. I couldn't turn it up in Google, either.


It was the announcement for enum 0.3:

<URL:http://groups.google.com/group/comp.lang.python/browse_thread/thread/ea5991de0459d5c4/>
Could I get you to recap the reason?


"Since the values of an enumeration are directly reflected in the
values and attributes, Enum instances are immutable to preserve
this relationship"

--
\ "I can picture in my mind a world without war, a world without |
`\ hate. And I can picture us attacking that world, because they'd |
_o__) never expect it." -- Jack Handey |
Ben Finney
Dec 2 '05 #84
bo****@gmail.com writes:
Mike Meyer wrote:
That's not a use case, that's a debugging aid. The same logic applies
to adding type declarations, private/public/etc. declerations, and
similar B&D language features. It's generally considered that it's not
a good enough reason for adding those, so it doesn't really constitute
a good enough reason for making an instance immutable. By design, this is a "don't use" feature so it would be very hard to
find a "use case" ;-)


But I can think of use cases for instances with no mutable attributes,
which is another "don't use" case. If I can do that, those proposing
that instances ought to be immutable should be able to come up with a
use case.
I can only think of a situation which may not be able to detect by
testing. Say I have a module version 1 which is used by app version 1.
In your app, you attach your own attribute to an instance of the
module. Everything is fine. Now module becomes version 2 which happens
to use the same attribute name that you hang on it and the program
starts to behave strangely because they are stepping on each other's
foot without knowing it. If everything is done by the same group of
people with good communication, it may be possible to detect it. But if
the module is done by a third party, and the app is done by yet another
third party. The situation becomes complicated. Say if under debian, I
do an apt-get python-sqlobject which may be used by multiple apps. If
one of them happens to do it this way, this senario may happen.


This is a problem with OO in general, not with not having immutable
instances. You get the same problem if, instead of attaching
attributes to your instances, I subclass your class and add the
attribute in the subclass (which I can do even if both my instances
and yours are immutable). In short, immutable instances don't solve
your problem, so this doesn't work as a use case.

<mike
--
Mike Meyer <mw*@mired.org> http://www.mired.org/home/mwm/
Independent WWW/Perforce/FreeBSD/Unix consultant, email for more information.
Dec 2 '05 #85
Ben Finney <bi****************@benfinney.id.au> writes:

"Since the values of an enumeration are directly reflected in the
values and attributes, Enum instances are immutable to preserve
this relationship"


This justifies making the attributes immutable. But that's old hat - I
had that use case last year. It doesn't justify making the instances
immutable. Or if it does, I missed it.

thanks,
<mike
--
Mike Meyer <mw*@mired.org> http://www.mired.org/home/mwm/
Independent WWW/Perforce/FreeBSD/Unix consultant, email for more information.
Dec 2 '05 #86

Mike Meyer wrote:
By design, this is a "don't use" feature so it would be very hard to
find a "use case" ;-)
But I can think of use cases for instances with no mutable attributes,
which is another "don't use" case. If I can do that, those proposing
that instances ought to be immutable should be able to come up with a
use case.

Lose you, can you clarify ?
This is a problem with OO in general, not with not having immutable
instances. You get the same problem if, instead of attaching
attributes to your instances, I subclass your class and add the
attribute in the subclass (which I can do even if both my instances
and yours are immutable). In short, immutable instances don't solve
your problem, so this doesn't work as a use case.

um, that could be true(already forgot if I can do this in say C++). How
would I solve this kind of issue then, just curious.

Dec 2 '05 #87
Mike Meyer <mw*@mired.org> wrote:
...
This is a problem with OO in general, not with not having immutable
instances. You get the same problem if, instead of attaching
attributes to your instances, I subclass your class and add the
attribute in the subclass (which I can do even if both my instances


So you'd have to make your class non-subclassable -- easy to do when
you're implementing a type in C, or with a custom metaclass. I guess
that's the motivation behind "final" classes in Java, btw -- arguably
one of the worst enablers of "designer hubris", of course;-)
Alex
Dec 2 '05 #88
bo****@gmail.com writes:
Mike Meyer wrote:
> By design, this is a "don't use" feature so it would be very hard to
> find a "use case" ;-)

But I can think of use cases for instances with no mutable attributes,
which is another "don't use" case. If I can do that, those proposing
that instances ought to be immutable should be able to come up with a
use case.

Lose you, can you clarify ?


There are lots of use cases where you want your attributes to be
immutable. Rationals, enums, anything where you want your instance to
contain some used as a "value", or usable as a dictionary key that
might equal other instances, or - well, you should get the idea.
This is a problem with OO in general, not with not having immutable
instances. You get the same problem if, instead of attaching
attributes to your instances, I subclass your class and add the
attribute in the subclass (which I can do even if both my instances
and yours are immutable). In short, immutable instances don't solve
your problem, so this doesn't work as a use case.

um, that could be true(already forgot if I can do this in say C++). How
would I solve this kind of issue then, just curious.


B&D languages have facilities for doing this kind of thing. Alex
Martelli has mentioned "final" classes in Java. C++ and Eiffel let you
declare an attribute as not modifiable by subclasses. Eiffel requires
that subclasses that override attributes (or methods, for that matter)
do so in a type-compatable manner, so you'd probably get a compile
error in your subclass in this case. There are certainly methods I've
never heard of as well. In Python, you can do things that try and
enforce this (I don't know how, because it's not something I think is
reasonable to want to do), but the language is also powerful enough
that I'd be surprised if they couldn't be defeated in some manner.

<mike
--
Mike Meyer <mw*@mired.org> http://www.mired.org/home/mwm/
Independent WWW/Perforce/FreeBSD/Unix consultant, email for more information.
Dec 2 '05 #89
Mike Meyer <mw*@mired.org> wrote:
Ben Finney <bi****************@benfinney.id.au> writes:
"Since the values of an enumeration are directly reflected in
the values and attributes, Enum instances are immutable to
preserve this relationship"


This justifies making the attributes immutable. But that's old hat -
I had that use case last year. It doesn't justify making the
instances immutable. Or if it does, I missed it.


The Enum class promises that instances will have all the enumeration
values as instance attributes, and that all the instance attributes
are values in the enumeration. That requires that the set of
attributes on the instance not be changed after creation.

--
\ "The future always arrives too fast, and in the wrong order." |
`\ -- Alvin Toffler |
_o__) |
Ben Finney
Dec 2 '05 #90
Ben Finney <bi****************@benfinney.id.au> writes:
Mike Meyer <mw*@mired.org> wrote:
Ben Finney <bi****************@benfinney.id.au> writes:
> "Since the values of an enumeration are directly reflected in
> the values and attributes, Enum instances are immutable to
> preserve this relationship"

This justifies making the attributes immutable. But that's old hat -
I had that use case last year. It doesn't justify making the
instances immutable. Or if it does, I missed it.

The Enum class promises that instances will have all the enumeration
values as instance attributes, and that all the instance attributes
are values in the enumeration. That requires that the set of
attributes on the instance not be changed after creation.


It doesn't say anything about that in the package, and there are no
docs in what's I downloaded from PyPI.

Doesn't live up to those promises, either.

But what's the point of promising that there won't be any attributes
that aren't values? Do you expect the user to know how to distinguish
implementation details from actual attributes(*), and get a list of
value names by filtering them from the attribute list? Wouldn't it be
easier to provide a method that returned a tuple of names - at least
easier than tuple(value.key for value in myenum)?

Sorry if you discussed this in the thread on the enum class, but I
didn't follow it.

<mike

*) Actually, the user is required to know implementation details, as
otherwise they'll have problems with value names that collide with
them.
--
Mike Meyer <mw*@mired.org> http://www.mired.org/home/mwm/
Independent WWW/Perforce/FreeBSD/Unix consultant, email for more information.
Dec 2 '05 #91

This thread has been closed and replies have been disabled. Please start a new discussion.

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.