Making immutable instances

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Mike Meyer

    #46
    Re: Making immutable instances

    "Giovanni Bajo" <noway@sorry.co m> writes:[color=blue]
    > Mike Meyer wrote:[color=green][color=darkred]
    >>> Björn Lindström wrote:
    >>> Why do you think we have a frozenset, for instance? By Mike's
    >>> argument, we shouldn't have it.[/color]
    >> Not *my* arguments, certainly. Not unless you're seriously
    >> misinterpreting them.[/color]
    > Sorry then, I probably am. There must be a misunderstandin g somewhere.[/color]

    I'm seeing posts from you attribute to "Mike Meyer" (me) and "Mike" -
    some of which definitely weren't me. So maybe it wasn't mine.
    [color=blue]
    > What is your position about frozenset? By my understanding of your arguments,
    > it is a hand-cuffed version of set, which just prevents bugs that could still
    > be caught by testing.[/color]

    I have exactly the same problem with frozensets as I do with sets - I
    can't add attributes to either one. That frozenset can't be changed
    doesn't bother me particularly.
    [color=blue]
    > The same applies for the arbitrary restriction of not allowing sets
    > to be key dictionaries (with their hash value being their id).[/color]

    I can't parse that. What do you mean by "key dictionaries"?

    <mike
    --
    Mike Meyer <mwm@mired.or g> http://www.mired.org/home/mwm/
    Independent WWW/Perforce/FreeBSD/Unix consultant, email for more information.

    Comment

    • Paul Rubin

      #47
      Re: Making immutable instances

      Mike Meyer <mwm@mired.or g> writes:[color=blue]
      > There isn't a standard serialize method in Python, so I don't know how
      > you want to define it.[/color]

      Well, consider pickle, for example.
      [color=blue]
      > I can think of perfectly reasonable definitions
      > of serialize where obj.serialize() won't always return the same string
      > on an immutable object, even if you don't allow adding attributes.[/color]

      Fair enough. How's this:

      a = ImmutableObject ()
      b = deepcopy(a)
      assert a == b # a and b start out equal
      .... do stuff ....
      # since a and b are immutable, they should still be equal
      # no matter what has happened above
      assert a == b

      If you've added attributes to a but not to b, they should compare
      unequal, breaking immutability.

      Comment

      • bonono@gmail.com

        #48
        Re: Making immutable instances


        Paul Rubin wrote:[color=blue]
        > Fair enough. How's this:
        >
        > a = ImmutableObject ()
        > b = deepcopy(a)
        > assert a == b # a and b start out equal
        > .... do stuff ....
        > # since a and b are immutable, they should still be equal
        > # no matter what has happened above
        > assert a == b
        >
        > If you've added attributes to a but not to b, they should compare
        > unequal, breaking immutability.[/color]

        How about this ?

        a=(1,[])
        b=copy.deepcopy (a)
        assert a==b # True
        a[1].append(1)
        assert a!=b

        Comment

        • Mike Meyer

          #49
          Re: Making immutable instances

          Paul Rubin <http://phr.cx@NOSPAM.i nvalid> writes:[color=blue]
          > Mike Meyer <mwm@mired.or g> writes:[color=green]
          >> There isn't a standard serialize method in Python, so I don't know how
          >> you want to define it.
          >> I can think of perfectly reasonable definitions
          >> of serialize where obj.serialize() won't always return the same string
          >> on an immutable object, even if you don't allow adding attributes.[/color]
          > Fair enough. How's this:
          >
          > a = ImmutableObject ()
          > b = deepcopy(a)
          > assert a == b # a and b start out equal
          > .... do stuff ....
          > # since a and b are immutable, they should still be equal
          > # no matter what has happened above
          > assert a == b
          >
          > If you've added attributes to a but not to b, they should compare
          > unequal, breaking immutability.[/color]

          Why should they compare unequal just because you add an attribute?
          Nothing says all attributes have to be involved in an equality
          comparison. In fact, Python classes by default ignore all attributes
          when doing an equality comparison. In order to compare attributes, you
          have to provide an __eq__ method (or __cmp__, but we'll ignore
          that). It can't mention your new attribute, because it doesn't exist
          unless you add it. So your final assertion will be true even after
          adding a new attribute.

          Of course, there's a fundamental flaw in your definition of
          "immutable" , in that there are immutable objects - tuples - for which
          the condition t1 == t2 is *not* a constant. Tuples can hold mutable
          objects, meaning you can change those. Doing so will make a tuple not
          compare equal to a copy of the state prior to changing the contents of
          the tuple.

          <mike
          --
          Mike Meyer <mwm@mired.or g> http://www.mired.org/home/mwm/
          Independent WWW/Perforce/FreeBSD/Unix consultant, email for more information.

          Comment

          • Steven D'Aprano

            #50
            Re: Making immutable instances

            On Thu, 24 Nov 2005 12:55:07 +0000, Antoon Pardon wrote:
            [color=blue]
            > Suppose I have the following code.
            >
            > from module import __take_care__
            >
            > __private_detai l__ = ...
            >
            > I now have two variable that are flaged the same way, but they are not.[/color]

            No, you have two names written using a poor naming convention.

            __name__ should be used only for Python's special methods.
            [color=blue]
            > __take_care__ is a private variable from an other module which I should
            > use with extreme care not to break the other package.[/color]

            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__n ame.

            Both techniques are done in order to let the module creator protect users
            from *accidentally* shooting themselves in the foot, while still allowing
            the module users to *deliberately* shoot themselves in the foot if that is
            what they need or want to do. Deliberately breaking these information
            hiding techniques are features, not bugs.

            [color=blue]
            > __private_detai l__ on the other hand is just keeping private data for my
            > own module, which I should care about as just any other variable in my
            > module.[/color]

            If you care about keeping __private_detai l__ no more than you care about
            public_detail, what makes one private and one public?

            [color=blue]
            > It are other modules that should take special care if they
            > should choose to import this variable.[/color]

            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.


            --
            Steven.

            Comment

            • Steven D'Aprano

              #51
              Re: Making immutable instances

              On Thu, 24 Nov 2005 11:44:16 -0500, Mike Meyer wrote:
              [color=blue]
              > In Python, I can even fix
              > it so *your* code uses my wrapped version:
              >
              > import Finney
              > class Addable(Finnney .Immutable): pass
              > Finney.Immutabl e = 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.[/color]

              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.

              Comment

              • Mike Meyer

                #52
                Re: Making immutable instances

                Steven D'Aprano <steve@REMOVETH IScyber.com.au> writes:[color=blue]
                > On Thu, 24 Nov 2005 11:44:16 -0500, Mike Meyer wrote:[color=green]
                >> In Python, I can even fix
                >> it so *your* code uses my wrapped version:
                >>
                >> import Finney
                >> class Addable(Finnney .Immutable): pass
                >> Finney.Immutabl e = Addable[/color]
                >
                > 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.[/color]

                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 <mwm@mired.or g> http://www.mired.org/home/mwm/
                Independent WWW/Perforce/FreeBSD/Unix consultant, email for more information.

                Comment

                • Steven D'Aprano

                  #53
                  Re: Making immutable instances

                  On Fri, 25 Nov 2005 20:50:41 -0500, Mike Meyer wrote:
                  [color=blue]
                  > Steven D'Aprano <steve@REMOVETH IScyber.com.au> writes:[color=green]
                  >> On Thu, 24 Nov 2005 11:44:16 -0500, Mike Meyer wrote:[color=darkred]
                  >>> In Python, I can even fix
                  >>> it so *your* code uses my wrapped version:
                  >>>
                  >>> import Finney
                  >>> class Addable(Finnney .Immutable): pass
                  >>> Finney.Immutabl e = Addable[/color]
                  >>
                  >> 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.[/color]
                  >
                  > 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.[/color]

                  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.

                  Comment

                  • Mike Meyer

                    #54
                    Re: Making immutable instances

                    Steven D'Aprano <steve@REMOVETH IScyber.com.au> writes:[color=blue]
                    > "Hmmm, the class designer didn't want me adding attributes to instances...
                    > maybe he had a good reason for that..."[/color]

                    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 <mwm@mired.or g> http://www.mired.org/home/mwm/
                    Independent WWW/Perforce/FreeBSD/Unix consultant, email for more information.

                    Comment

                    • Steven D'Aprano

                      #55
                      Re: Making immutable instances

                      On Fri, 25 Nov 2005 23:20:05 -0500, Mike Meyer wrote:
                      [color=blue]
                      > Steven D'Aprano <steve@REMOVETH IScyber.com.au> writes:[color=green]
                      >> "Hmmm, the class designer didn't want me adding attributes to instances...
                      >> maybe he had a good reason for that..."[/color]
                      >
                      > 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.[/color]

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

                      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.

                      Comment

                      • Mike Meyer

                        #56
                        Re: Making immutable instances

                        Steven D'Aprano <steve@REMOVETH IScyber.com.au> writes:[color=blue]
                        > On Fri, 25 Nov 2005 23:20:05 -0500, Mike Meyer wrote:[color=green]
                        >> If you've got a use case, I'd be interested in hearing it.[/color]
                        > frozenset perhaps? If it were needed once, it could be needed again.[/color]

                        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.
                        [color=blue]
                        > 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.[/color]

                        How does the ability to add attributes to the instances of the class
                        change that behavior?
                        [color=blue]
                        > 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.[/color]

                        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 <mwm@mired.or g> http://www.mired.org/home/mwm/
                        Independent WWW/Perforce/FreeBSD/Unix consultant, email for more information.

                        Comment

                        • Steven D'Aprano

                          #57
                          Re: Making immutable instances

                          On Sat, 26 Nov 2005 04:59:59 -0500, Mike Meyer wrote:
                          [color=blue]
                          > Steven D'Aprano <steve@REMOVETH IScyber.com.au> writes:[color=green]
                          >> On Fri, 25 Nov 2005 23:20:05 -0500, Mike Meyer wrote:[color=darkred]
                          >>> If you've got a use case, I'd be interested in hearing it.[/color]
                          >> frozenset perhaps? If it were needed once, it could be needed again.[/color]
                          >
                          > That's not a use case, that's an example.[/color]

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

                          [color=blue]
                          > 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.[/color]

                          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?

                          [color=blue][color=green]
                          >> 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.[/color]
                          >
                          > How does the ability to add attributes to the instances of the class
                          > change that behavior?[/color]

                          Er, who said it did?

                          [color=blue][color=green]
                          >> 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.[/color]
                          >
                          > 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.[/color]

                          I can't disagree with you there.
                          [color=blue]
                          > The best reason Ben could come up with is that it makes
                          > finding bugs a bit easier.[/color]

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

                          [color=blue]
                          > 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.[/color]

                          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.

                          [color=blue]
                          > 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?[/color]

                          Class instances match by identity when used as keys, not equality. That's
                          over-strict: why should Parrot("Norwegi an Blue") map to a different item
                          from Parrot("Norwegi an" + " 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.

                          Comment

                          • Mike Meyer

                            #58
                            Re: Making immutable instances

                            Steven D'Aprano <steve@REMOVETH IScyber.com.au> writes:[color=blue]
                            > On Sat, 26 Nov 2005 04:59:59 -0500, Mike Meyer wrote:[color=green]
                            >> Steven D'Aprano <steve@REMOVETH IScyber.com.au> writes:[color=darkred]
                            >>> 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.[/color]
                            >> That's not a use case, that's an example.[/color]
                            > Fine. "I want to use a set as a dictionary key, but dict keys must be
                            > immutable."[/color]

                            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.
                            [color=blue][color=green]
                            >> 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.[/color]
                            > Every builtin type, including mutable sets, is immutable???[/color]

                            No. I think you missed the entire second half the thread.
                            [color=blue]
                            > I think we're talking at cross purposes. I'm talking about immutable
                            > instances. What are you talking about?[/color]

                            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.
                            [color=blue][color=green][color=darkred]
                            >>> 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.[/color]
                            >> How does the ability to add attributes to the instances of the class
                            >> change that behavior?[/color]
                            > Er, who said it did?[/color]

                            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.
                            [color=blue][color=green]
                            >> The best reason Ben could come up with is that it makes
                            >> finding bugs a bit easier.[/color]
                            > Are you sure that was Ben? Maybe I missed it.[/color]

                            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.
                            [color=blue]
                            > All joking aside, I think having immutable custom classes, with or without
                            > restricting attribute creation, is no worse than (say) Python's name
                            > mangling.[/color]

                            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?
                            [color=blue][color=green]
                            >> 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?[/color]
                            > Class instances match by identity when used as keys, not equality. That's
                            > over-strict: why should Parrot("Norwegi an Blue") map to a different item
                            > from Parrot("Norwegi an" + " Blue") just because the first instance has a
                            > different memory location to the second?[/color]

                            Uh - HTH did we get here?
                            [color=blue]
                            > 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.[/color]

                            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("Norwegi an Blue") == Parrot("Norwegi an" + " Blue")
                            always evaluates to True.
                            [color=blue]
                            > 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.[/color]

                            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 <mwm@mired.or g> http://www.mired.org/home/mwm/
                            Independent WWW/Perforce/FreeBSD/Unix consultant, email for more information.

                            Comment

                            • Antoon Pardon

                              #59
                              Re: Making immutable instances

                              Op 2005-11-26, Steven D'Aprano schreef <steve@REMOVETH IScyber.com.au> :[color=blue]
                              > On Thu, 24 Nov 2005 12:55:07 +0000, Antoon Pardon wrote:
                              >[color=green]
                              >> Suppose I have the following code.
                              >>
                              >> from module import __take_care__
                              >>
                              >> __private_detai l__ = ...
                              >>
                              >> I now have two variable that are flaged the same way, but they are not.[/color]
                              >
                              > No, you have two names written using a poor naming convention.[/color]

                              Well if it is a poor naming convention, why react to me, and not to
                              Mike who was defending this poor naming convention?
                              [color=blue]
                              > __name__ should be used only for Python's special methods.
                              >[color=green]
                              >> __take_care__ is a private variable from an other module which I should
                              >> use with extreme care not to break the other package.[/color]
                              >
                              > 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__n ame.[/color]

                              We were not talkin about special treatment by python. We were talking
                              about conventions to communicate purpose to other readers of the
                              software.
                              [color=blue][color=green]
                              >> It are other modules that should take special care if they
                              >> should choose to import this variable.[/color]
                              >
                              > 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.[/color]

                              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

                              Comment

                              • Paul Rubin

                                #60
                                Re: Making immutable instances

                                Mike Meyer <mwm@mired.or g> writes:[color=blue]
                                > 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.[/color]

                                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, DynamicAttribut eMixin):
                                ...

                                However, that's not likely to happen.

                                Comment

                                Working...