Finding the instance reference of an object

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Larry Bates

    #16
    Re: Finding the instance reference of an object

    Joe Strout wrote:
    On Oct 16, 2008, at 10:59 AM, Larry Bates wrote:
    >
    >>how do i find that the name is 'bob'
    >>
    >Short answer is that you can't. This because Python's names (bob) are
    >bound to objects (modulename.obj ectname()). They are NOT variables as
    >they are in "other" programming languages.
    >
    Which other programming languages? I've never seen an OOP language that
    didn't work the same way as Python.
    >
    However, 'bob' here really is a variable. It's a variable whose value
    (at the moment) is a reference to some object.
    >
    >It is perfectly legal in Python to bind multiple names to a single
    >object:
    >>
    >a=b=c=modulena me.objectname()
    >
    Right -- three variables (a, b, and c) that all have the same value,
    i.e. all refer to the same object. There's nothing more mysterious here
    than
    >
    i=j=k=42
    >
    where i, j, and k all have the same value. (The OP's question would be
    like asking "what is the name of the variable referring to 42? And
    while you might, in theory, be able to produce a list of all such
    variables by trolling through the Python's internals, it's a bit of a
    silly thing to do.)
    >
    >a, b, and c all point to the same object. An object can have an
    >unlimited number of names bound to it. This is one of the most
    >difficult concepts for many beginning Python programmers to understand
    >(I know I had a difficult time at first). It is just not how we
    >taught ourselves to think about "variables" and you can write quite a
    >lot of Python treating the names you bind to objects like they were
    >"variables" .
    >
    Well, they are variables. I'm not quite grasping the difficulty here...
    unless perhaps you were (at first) thinking of the variables as holding
    the object values, rather than the object references. That is indeed
    something important to grasp, since it explains why if you do
    >
    a = b # where b was some object with an attribute 'foo'...
    a.foo = 42
    >
    ...you now find that b.foo is 42 too. Nothing mysterious once you
    realize that the value of a and b is a reference to some object that has
    a "foo" attribute.
    >
    Not sure if all this was helpful to anyone, but I hope so!
    >
    Best,
    - Joe
    >
    Sorry Joe, but I respectfully disagree about "not being mysterious". I've been
    on this list for about 8 years and this question/issue comes up EVERY week with
    newbies. Python names are just not variables in the traditional sense. If they
    were then:

    a=b=c=[42]

    would create three independent variables that each contained a list with a
    single element of 42. That is not what Python does and just about every newbie
    gets bitten by that fact at least once.

    ow many posts have a read here where people do things like:

    a = [1,2,3,4,5]
    b = a
    b.append(6)

    and can't figure out why a now contains [1,2,3,4,5,6]?

    Without fail they thought that b = a copied the contents of a into b. That is,
    they thought of a and b as variables that "hold" values. Now the term
    "variables" may mean something different to you than most of the other newbies
    that frequent this list, but they all (including me when I first started) miss
    the subtilety of the name/value bindings at first (but boy are they beautiful
    when you finally see the light). Perhaps you were lucky and were able to grasp
    this quite powerful concept more easily than most of us.

    I think this is one of the most difficult concepts about Python to grasp for
    people coming from VB, C, Fortran, Cobol (oops showed my age there), etc. We
    trained our minds to treat "variables" like named buckets (or memory locations).
    Even the OP here wants to interrogate the object in the bucket and coerce it
    into giving him the bucket (variable) name.

    The problem, as Steven so eloquently shows in a separate post, is that is is
    hard to talk about names that are bound to objects. So we fall back into
    familiar language and use "variable" which confuses a lot of newbies because
    they have preconceived notion about what a "variable" is and what it does.

    Regards,
    Larry

    Comment

    • Joe Strout

      #17
      Re: Finding the instance reference of an object

      On Oct 16, 2008, at 7:30 PM, Steven D'Aprano wrote:
      >However, 'bob' here really is a variable. It's a variable whose
      >value
      >(at the moment) is a reference to some object.
      >
      Traditionally, a "variable" is a named memory location.
      Agreed.
      The main objection I have to using "variable" to describe Python name/
      value bindings is that it has connotations that will confuse
      programmers
      who are familiar with C-like languages. For example:
      >
      def inc(x):
      x += 1
      >
      n = 1
      inc(n)
      assert n == 2
      >
      Why doesn't that work? This is completely mysterious to anyone
      expecting
      C-like variables.
      Hmm... I'm not following you. That wouldn't work in C, either. 'x'
      in 'inc' is a local variable; its value is just a copy of whatever
      value you pass in. You can increment it all you want, and it won't
      affect the original variable (if indeed it was a variable that the
      value came from; it could be a literal or an expression or who knows
      what else).
      At this point people will often start confusing the issue by claiming
      that "all Python variables are pointers", which is an *implementation
      detail* in CPython but not in other implementations , like PyPy or
      Jython.
      I'm not claiming that -- and I'm trying to clarify, rather than
      confuse the issue. (Of course if it turns out that my understanding
      of Python is incorrect, then I'm hoping to uncover and correct that,
      too.)
      Or people will imagine that Python makes a copy of the variable when
      you
      call a function. That's not true, and in fact Python explicitly
      promises
      never to copy a value unless you explicitly tell it to
      Now that IS mysterious. Doesn't calling a function add a frame to a
      stack? And doesn't that necessitate copying in values for the
      variables in that stack frame (such as 'x' above)? Of course we're
      now delving into internal implementation details... but it sure
      behaves as though this is exactly what it's doing (and is the same
      thing every other language does, AFAIK).
      but it seems to explain the above, at least until the programmer
      starts *assuming* call-
      by-value behaviour and discovers this:
      >
      def inc(alist):
      alist += [1] # or alist.append(1) if you prefer
      return alist
      It's still call-by-value behavior. The value in this case is a list
      reference. Using .append, or the += operator, modifies the list
      referred to by that list reference. Compare that to:

      def inc(alist):
      alist = alist + [1]
      return alist

      where you are not modifying the list passed in, but instead creating a
      new list, and storing a reference to that in local variable 'alist'.

      The semantics here appear to be exactly the same as Java or REALbasic
      or any other modern language: variables are variables, and parameters
      are local variables with called by value, and it just so happens that
      some values may be references to data on the heap.
      Are functions call by value or call by reference???
      >
      (Answer: neither. They are call by name.)
      I have no idea what that means. They're call by value as far as I can
      tell. (Even if the value may happen to be a reference.)

      Side question, for my own education: *does* Python have a "ByRef"
      parameter mode?
      I myself often talk about variables as shorthand. But it's a bad
      habit,
      because it is misleading to anyone who thinks they know how variables
      behave, so when I catch myself doing it I fix it and talk about name
      bindings.
      Perhaps you have a funny idea of what people think about how variables
      behave. I suspect that making up new terminology for perfectly
      ordinary things (like Python variables) makes them more mysterious,
      not less.
      Of course, you're entitled to define "variable" any way you like, and
      then insist that Python variables don't behave like variables in other
      languages. Personally, I don't think that's helpful to anyone.
      No, but if we define them in the standard way, and point out that
      Python variables behave exactly like variables in other languages,
      then that IS helpful.
      >Well, they are variables. I'm not quite grasping the difficulty
      >here...
      >unless perhaps you were (at first) thinking of the variables as
      >holding
      >the object values, rather than the object references.
      >
      But that surely is what almost everyone will think, almost all the
      time.
      Consider:
      >
      x = 5
      y = x + 3
      >
      I'm pretty sure that nearly everyone will read it as "assign 5 to x,
      then
      add 3 to x and assign the result to y" instead of:
      >
      "assign a reference to the object 5 to x, then dereference x to get
      the
      object 5, add it to the object 3 giving the object 8, and assign a
      reference to that result to y".
      True. I have no reason to believe that, in the case of a number, the
      value isn't the number itself. (Except for occasional claims that
      "everything in Python is an object," but if that's literally true,
      what are the observable implications?)
      Of course that's what's really happening under the hood, and you can't
      *properly* understand how Python behaves without understanding that.
      But
      I'm pretty sure few people think that way naturally, especially noobs.
      In this sense I'm still a noob -- until a couple weeks ago, I hadn't
      touched Python in over a decade. So I sure appreciate this
      refresher. If numbers really are wrapped in objects, that's
      surprising to me, and I'd like to learn about any cases where you can
      actually observe this. (It's not apparent from the behavior of the +=
      operator, for example... if they are objects, I would guess they are
      immutable.)

      But it's not at all surprising with lists and dicts and objects --
      every modern language passes around references to those, rather than
      the data themselves, because the data could be huge and is often
      changing size all the time. Storing the values in a variable would
      just be silly.
      References are essentially like pointers, and learning pointers is
      notoriously difficult for people.
      Hmm... I bet you're over 30. :) So am I, for that matter, so I can
      remember when people had to learn "pointers" and found it difficult.
      But nowadays, the yoots are raised on Java, or are self-taught on
      something like REALbasic or .NET (or Python). There aren't any
      pointers, but only references, and the semantics are the same in all
      those languages. Pointer difficulty is something that harkens back to
      C/C++, and they're just not teaching that anymore, except to the EE
      majors.

      So, if the semantics are all the same, I think it's helpful to use the
      standard terminology.
      Python does a magnificent job of making
      references easy, but it does so by almost always hiding the fact
      that it
      uses references under the hood. That's why talk about variables is so
      seductive and dangerous: Python's behaviour is *usually* identical
      to the
      behaviour most newbies expect from a language with "variables" .
      You could be right, when it comes to numeric values -- if these are
      immutable objects, then I can safely get by thinking of them as pure
      values rather than references (which is what they are in RB, for
      example). Strings are another such case: as immutable, you can safely
      treat them as values, but it's comforting to know that you're not
      incurring the penalty of copying a huge data buffer every time you
      pass one to a function or assign it to another variable.

      But with mutable objects, it is ordinary and expected that what you
      have is a reference to the object, and you can tell this quite simply
      by mutating the object in any way. Every modern language I know works
      the same way, and I'd wager that the ones I don't know (e.g. Ruby)
      also work that way. Python's a beautiful language, but I'm afraid
      it's nothing special in this particular regard.

      Best,
      - Joe

      Comment

      • Joe Strout

        #18
        Re: Finding the instance reference of an object

        On Oct 16, 2008, at 11:23 PM, Dennis Lee Bieber wrote:
        On Thu, 16 Oct 2008 21:19:28 -0600, Joe Strout <joe@strout.net >
        declaimed the following in comp.lang.pytho n:
        >
        >Now that IS mysterious. Doesn't calling a function add a frame to a
        >stack? And doesn't that necessitate copying in values for the
        >variables in that stack frame (such as 'x' above)? Of course we're
        >
        No -- it copies the /reference/ to the object containing the value.
        The reference to the object IS the value of an object reference
        variable. So good, parameters are passed ByVal in Python as they
        appear to be, and as is the default in every other modern language.
        Just as assignment transfers the reference to the RHS object to the
        name
        shown on the LHS.
        Assignment copies the RHS value to the LHS variable. In the case of
        an object reference, the value copied is, er, an object reference.
        >The semantics here appear to be exactly the same as Java or REALbasic
        >or any other modern language: variables are variables, and parameters
        >are local variables with called by value, and it just so happens that
        >some values may be references to data on the heap.
        >>
        ALL "values" are references to data in Python -- but some of those
        values are immutable objects so any operation performed on them
        creates
        new objects, and the assignment is of a new reference.
        OK, that part is a little different from most languages -- not in the
        way objects are treated, but in the fact that even simple values like
        integers are wrapped in objects. But since those are immutable
        objects, this is mostly an internal implementation detail.

        For object references (including the mutable ones that may treat
        people up), Python's behavior is no different from any other language.
        >>(Answer: neither. They are call by name.)
        >>
        >I have no idea what that means. They're call by value as far as I
        >can
        >tell. (Even if the value may happen to be a reference.)
        >
        Technically, as I recall the definition of "call by name", they
        aren't that either. ...
        Call by name, then, acted as a macro expansion wherever the argument
        was referenced in the called function.
        Thanks for that explanation. Clearly that's not what's going on in
        Python.
        >Side question, for my own education: *does* Python have a "ByRef"
        >parameter mode?
        >>
        As far as I'm concerned -- everything is "by ref" in Python...
        No, a "by ref" parameter would mean that this:

        def foo(ByRef x):
        x = x + [42]

        a = [1,2,3]
        foo(a)

        ....would result in a = [1,2,3,42]. You would only be able to pass a
        simple variable (not an expression or literal) to foo, and the 'x'
        inside foo would not be a local variable, but an alias of whatever
        variable was passed in. Thus any assignments to it would affect the
        original variable that was passed in.

        But if Python has any such feature, I'm not aware of it. Certainly
        the default behavior is to pass everything (even object references) by
        value. Assignments made to them don't affect anything else.
        Mutation of an object is never a bare LHS... It is either a method
        call of the name
        >
        alist.append()
        >
        or a drill-down going inside the object
        >
        alist[2] = something
        anobject.attrib ute = something
        adict["key"] = something
        Or, use of one of the compound operators like +=. That's the only
        real "gotcha" in Python to somebody coming from another language; you
        might naively expect that x += y is the same as x = x+y, but in Python
        this is not generally the case; instead += is a mutation operator,
        like the examples you show above.
        But every language I've used (many: FORTRAN, C, C++, BASIC, VB,
        Assembly, COBOL, Ada...) treats "variable" as "name of fixed
        location in
        memory" and assignment to the variable means "replace the contents of
        the location of memory associated with this name with the contents of
        memory to which that name (may be anonymous in the case of an
        expression) is associated by copying the contents from there to here"
        That's what Python does too. It just so happens that the fixed
        location in memory contains an object reference. No difference here
        between Python's object references VB.NET's object references, C++
        pointers, Java object references, etc. etc.
        Python, OTOH, ALWAYS handles assignment as "change the memory
        association of this name to be the same as that name".
        What does that mean, exactly? It means: "replace the contents (i.e.
        object reference) of the memory location associated with this name
        with the contents (i.e. object reference) of the memory to which that
        name is associated by copying the contents from there to here."

        It's the exact same thing. (And exactly the same as in any other
        language.)
        >No, but if we define them in the standard way, and point out that
        >Python variables behave exactly like variables in other languages,
        >then that IS helpful.
        >>
        But they don't...
        They really, really do.
        >But it's not at all surprising with lists and dicts and objects --
        >every modern language passes around references to those, rather than
        >the data themselves, because the data could be huge and is often
        >changing size all the time. Storing the values in a variable would
        >just be silly.
        >>
        In most all of those languages, one has to explicitly differentiate
        the the difference between a copy and a reference.
        Only if you're thinking of languages from 20 years ago or more. Even
        in C++, while there is a different bit of kludgy syntax for object
        "references " (because they're mere pointers), it's the standard to use
        such pointers everywhere that objects are handled. Java cleaned up
        that kludginess by replacing the pointers with proper references, as
        did VB.NET, REALbasic, probably Ruby, and of course Python.
        And even that is not
        assured... As I recall, nothing in the Ada language reference forbids
        implementing an "in out" procedure parameter from being implemented
        via
        copy-in/copy-out semantics rather than via reference.
        Hah, well probably so. Ada even predates me, and I'm not all that
        young anymore!
        >Hmm... I bet you're over 30. :) So am I, for that matter, so I can
        >remember when people had to learn "pointers" and found it difficult.
        >
        Bah... The roots of I/O in Pascal required pointer dereferencing.
        Hey, I remember Pascal... that was the language used on the Apple
        IIGS, back when I was in junior high. I also remember spending $800
        for a 40MB hard drive for it. Ah, those were the days!
        >So, if the semantics are all the same, I think it's helpful to use
        >the
        >standard terminology.
        >>
        But, it seems, you are the only one arguing that "the semantics are
        all the same"... Doesn't that suggest that they aren't the same?
        No, it suggests to me that there's a lot of confusion in the Python
        community. :) It appears as though people either (a) really want to
        think that Python's object handling is special and unique for
        emotional reasons, or (b) are comparing it to really ancient languages
        that didn't have any notion of objects and object references. This
        has led to making up new terminology and spreading confusion. I'm
        coming back to Python from almost a decade of working with other
        modern languages (including implementing the compiler for one of
        them), and I don't see any difference at all between Python's object
        handling and those.

        Best,
        - Joe


        Comment

        • Aaron \Castironpi\ Brady

          #19
          Re: Finding the instance reference of an object

          On Oct 17, 10:56 am, Joe Strout <j...@strout.ne twrote:
          On Oct 16, 2008, at 11:23 PM, Dennis Lee Bieber wrote:
          snip
             But, it seems, you are the only one arguing that "the semantics are
          all the same"... Doesn't that suggest that they aren't the same?
          >
          No, it suggests to me that there's a lot of confusion in the Python  
          community.  :)  It appears as though people either (a) really want to 
          think that Python's object handling is special and unique for  
          emotional reasons, or (b) are comparing it to really ancient languages  
          that didn't have any notion of objects and object references.  This  
          has led to making up new terminology and spreading confusion.  I'm  
          coming back to Python from almost a decade of working with other  
          modern languages (including implementing the compiler for one of  
          them), and I don't see any difference at all between Python's object  
          handling and those.
          >
          Best,
          - Joe
          I'm not fluent in Java so you'll have to be the judge.

          In Python:

          b= 0
          f( b )

          No matter what, b == 0. C doesn't guarantee this. Does Java?

          Further:

          b= {}
          c= b
          f( b )

          No matter what, 'c is b' is true. C doesn't have an 'is' operator.
          Does Java?

          Lastly, the word 'same' is ambiguous or poorly defined. It can mean
          either 'identical' or 'equal'.

          Comment

          • Joe Strout

            #20
            Re: Finding the instance reference of an object

            On Oct 17, 2008, at 1:03 PM, Aaron Castironpi Brady wrote:
            I'm not fluent in Java so you'll have to be the judge.
            >
            In Python:
            >
            b= 0
            f( b )
            >
            No matter what, b == 0. C doesn't guarantee this.
            It does, unless f's parameter has been declared a reference
            parameter. (In C++, you'd do this with '&'; I didn't think it was
            possible in C, but it's been a long time since I've used C so maybe it
            is possible nowadays.)
            Does Java?
            Same in Java, and in RB, and in .NET too. If f's parameter is a by-
            value parameter, then it acts exactly like Python. (Those languages
            also allow a by-reference parameter declaration, which I think Python
            doesn't allow, but by-value is the default.)
            Further:
            >
            b= {}
            c= b
            f( b )
            >
            No matter what, 'c is b' is true.
            Right, again, this just demonstrates that Python passes values by
            reference.
            C doesn't have an 'is' operator.
            Well, that's literally true, but only because it doesn't have a deep
            equality operator like modern languages. In C, b and c would be
            pointers, and 'c == b' would be the equivalent of Python's 'c is
            b' (and would be true after the call to f, again assuming you didn't
            go out of your way to declare f with a by-reference parameter).
            Does Java?
            Yes. The behavior's the same. Same also in every other OOP language,
            as far as I know.

            I think all we've established here is that Python always passes
            parameters by value, and in most other languages, passing by value is
            the default (but there's an option to pass by reference if you want).

            Python lacks the ByRef-parameter feature, so when that's what you need
            to do, you'd have to wrap your value in some mutable type (like a
            list) and pass that instead. A little awkward, but no big deal, as
            there are darn few valid reasons to ever pass something by reference
            anyway, especially in a language with tuple packing and unpacking.

            Best,
            - Joe


            Comment

            • Aaron \Castironpi\ Brady

              #21
              Re: Finding the instance reference of an object

              On Oct 17, 4:03 pm, Joe Strout <j...@strout.ne twrote:
              On Oct 17, 2008, at 2:36 PM, Steve Holden wrote:
              snip
              And here, you're doing an assignment -- this is the only test of the  
              three that tests whether the parameter is passed by reference or by  
              value.  The result: it's by value.
              >
              So, is it call by reference or not?
              >
              Not.
              But it's not by value, q.e.d.
              snip
              ...except, of course, that Python's syntax is cleaner...
              Excepting that thou then proceedst to 3.

              snip

              Comment

              • George Sakkis

                #22
                Re: Finding the instance reference of an object

                On Oct 17, 5:19 pm, Grant Edwards <gra...@visi.co mwrote:
                On 2008-10-17, Joe Strout <j...@strout.ne twrote:
                >
                And my real point is that this is exactly the same as in every
                other modern language.
                ^^^^^^^^^
                No, it isn't. In many other languages (C, Pascal, etc.), a
                ^^^^^^^^^^^^^^^ ^^
                Methinks the only real disagreement in this thread is what's a
                "modern" language; Joe has made clear that he's not comparing Python
                to C, Pascal or Fortran.

                George

                Comment

                • Steven D'Aprano

                  #23
                  Re: Finding the instance reference of an object

                  On Fri, 17 Oct 2008 16:36:24 -0400, Steve Holden wrote:
                  People here don't describe Python as different just because they *want*
                  it to be different. Python acknowledges intellectual debts to many
                  languages, none of which is exactly like it.
                  I understand that Python's object and calling semantics are exactly the
                  same as Emerald (and likely other languages as well), and that both
                  Emerald and Python are explicitly based on those of CLU, as described by
                  by Barbara Liskov in 1979:

                  "In particular it is not call by value because mutations
                  of arguments performed by the called routine will be
                  visible to the caller. And it is not call by reference
                  because access is not given to the variables of the
                  caller, but merely to certain objects."



                  quoted by Fredrik Lundh here:



                  "Call by object/sharing" isn't some new-fangled affectation invented by
                  comp.lang.pytho n dweebs to make Python seem edgy and different. It's a
                  term that has been in use in highly respected Comp Sci circles for over
                  thirty years. In case anybody doesn't recognise the name:




                  --
                  Steven

                  Comment

                  • Steven D'Aprano

                    #24
                    Re: Finding the instance reference of an object

                    On Fri, 17 Oct 2008 09:56:17 -0600, Joe Strout wrote:
                    On Oct 16, 2008, at 11:23 PM, Dennis Lee Bieber wrote:
                    >
                    >On Thu, 16 Oct 2008 21:19:28 -0600, Joe Strout <joe@strout.net >
                    >declaimed the following in comp.lang.pytho n:
                    >>
                    >>Now that IS mysterious. Doesn't calling a function add a frame to a
                    >>stack? And doesn't that necessitate copying in values for the
                    >>variables in that stack frame (such as 'x' above)? Of course we're
                    >>
                    > No -- it copies the /reference/ to the object containing the value.
                    >
                    The reference to the object IS the value of an object reference
                    variable.
                    That's a bizarre and unnatural way of looking at it. To steal a line from
                    the effbot, that's like valuing your child's Social Security number over
                    the child herself:




                    If we execute a line of Python code:

                    x = "parrot"

                    and then ask "What's the value of x?", I think that even you would think
                    I was being deliberately obtuse, difficult and obfuscatory if I answered
                    "location 0xb7cdeb2c".

                    So good, parameters are passed ByVal in Python as they appear
                    to be, and as is the default in every other modern language.
                    Nonsense. Python doesn't copy a parameter before passing it to the
                    function. You get the same parameter inside the function as outside:
                    >>def foo(x):
                    .... print id(x)
                    ....
                    >>a = ['some', 'thing']
                    >>print id(a); foo(a)
                    3083441036
                    3083441036


                    I'm going to anticipate your response here: you're going to deny that
                    call by value implies that the list ['some', 'thing'] will be copied
                    before being passed to the function. According to *some* definitions of
                    CBV, you might even be right. But according to *other* definitions,
                    including the one that I learned in comp sci at university, that copying
                    of data is an essential part of CBV.

                    These other definitions aren't necessarily a formal definition from some
                    Computer Scientist. They're just as likely to be informal understandings
                    of what CBV and CBR mean: "if it's call by value, don't pass big data
                    structures because they will be copied and your code will be slow".

                    >Just as assignment transfers the reference to the RHS object to the
                    >name
                    >shown on the LHS.
                    >
                    Assignment copies the RHS value to the LHS variable. In the case of an
                    object reference, the value copied is, er, an object reference.
                    No, assignment binds an object to a name. That's what Python does.

                    Of course, at the implementation level, name binding might be implemented
                    by copying object references. Or it might not. That's an implementation
                    detail that isn't relevant at the Python level.

                    Or at least, it shouldn't be relevant until the abstraction leaks.
                    There’s a key piece of magic in the engineering of the Internet which you rely on every single day. It happens in the TCP protocol, one of the fundamental building blocks of the Internet. TCP…




                    [snip]
                    For object references (including the mutable ones that may treat people
                    up), Python's behavior is no different from any other language.
                    That's an exceedingly broad claim. No different from Java? Well, perhaps.
                    No different from Lisp? Doubtful. No different from Forth? Yeah, riiight.

                    Speaking of Java, there's one major difference between Java and Python
                    with respect to names. In a statically typed language like Java, you
                    define names before you use them, and from that point the name is bound
                    to both a type and an object. But the binding to the object is optional,
                    and such unbound names are said to be null.

                    In a dynamically typed language like Python, names are bound only to
                    objects. You can't have an unbound name: if a name exists, it must be
                    bound to an object, and if it doesn't exist, you get a NameError
                    exception when you try to access it. And objects are typed, not names.





                    >>>(Answer: neither. They are call by name.)
                    >>>
                    >>I have no idea what that means. They're call by value as far as I can
                    >>tell. (Even if the value may happen to be a reference.)
                    >>
                    > Technically, as I recall the definition of "call by name", they
                    >aren't that either. ...
                    >Call by name, then, acted as a macro expansion wherever the argument
                    >was referenced in the called function.
                    >
                    Thanks for that explanation. Clearly that's not what's going on in
                    Python.
                    Ah no, that's my bad. I have a strange and disturbing mental stutter that
                    substitutes "call by name" when I mean to say "call by object" at the
                    most embarrassing times. Sorry.




                    --
                    Steven

                    Comment

                    • Steve Holden

                      #25
                      Re: Finding the instance reference of an object

                      Steven D'Aprano wrote:
                      [...]
                      when you talk about "call by value
                      where the value is a reference", it sounds to me as if you are insisting
                      that cars are ACTUALLY horse and buggies, where the horse is the engine,
                      why are we inventing new terms like 'automobile', that just confuses
                      people.
                      >
                      +1 QOTW
                      --
                      Steve Holden +1 571 484 6266 +1 800 494 3119
                      Holden Web LLC http://www.holdenweb.com/

                      Comment

                      • Steve Holden

                        #26
                        Re: Finding the instance reference of an object

                        Steven D'Aprano wrote:
                        [...]
                        when you talk about "call by value
                        where the value is a reference", it sounds to me as if you are insisting
                        that cars are ACTUALLY horse and buggies, where the horse is the engine,
                        why are we inventing new terms like 'automobile', that just confuses
                        people.
                        >
                        +1 QOTW
                        --
                        Steve Holden +1 571 484 6266 +1 800 494 3119
                        Holden Web LLC http://www.holdenweb.com/

                        Comment

                        • Fuzzyman

                          #27
                          Re: Finding the instance reference of an object

                          On Oct 17, 10:39 pm, Joe Strout <j...@strout.ne twrote:
                          On Oct 17, 2008, at 3:19 PM, Grant Edwards wrote:
                          >
                          And my real point is that this is exactly the same as in every
                          other modern language.
                          >
                          No, it isn't.  In many other languages (C, Pascal, etc.), a
                          "variable" is commonly thought of as a fixed location in memory
                          into which one can put values.  Those values may be references
                          to objects.
                          >
                          Right, though not in languages like C and Pascal that don't HAVE the  
                          notion of objects.  We really ought to stop bringing up those  
                          dinosaurs and instead compare Python to any modern OOP language.
                          >
                           In Python, that's not how it works.  There is no
                          "location in memory" that corresponds to a variable with a
                          particular name the way there is in C or Pascal or Fortran or
                          many other languages.
                          >
                          No?  Is there any way to prove that, without delving into the Python  
                          source itself?
                          >

                          ..NET makes a clear distinction between 'value types' and reference
                          types. These are analagous to the call by value and call by reference
                          that have been discussed in this thread.

                          My understanding of the difference is that value types (all numeric
                          types, structs, enumerations etc) actually live on the stack, whereas
                          reference types (strings, classes etc) live in the heap and have a
                          pointer on the stack.

                          It is complicated by the fact that .NET perpetuates the myth that the
                          primitives (the value types) inherit from System.Object (a reference
                          type). The runtime does auto-boxing for you where this matters.

                          This means that when you pass a value type into a method the value
                          *is* copied. Structs can be arbitrarily big, so this can be a
                          performance problem. It is often a performance win for working with
                          the numeric types as you remove a level of indirection.

                          It isn't without problems though - and some of these can be seen in
                          IronPython.

                          System.Drawing. Point is a struct, but it is effectively a mutable
                          value type. However, when you access it you are often accessing a copy
                          - and if you attempt to mutate it then your changes will be lost.

                          The following code illustrates the problem:
                          >>r = Rectangle(0, 1002 20, 40)
                          >>r.Location. X
                          0
                          >>r.Location. X = 20
                          >>r.Location. X
                          0

                          Because r.Location returns a value type, the update to it is 'lost'.

                          By this definition Python objects (all of them) are clearly reference
                          types and not value types.

                          In .NET you can specify that a parameter to a method takes a reference
                          ('out' in C# or ByRef in VB.NET). If you pass in a value type as a
                          reference parameter then the .NET runtime will do boxing / unboxing
                          for you.

                          This means that we can write code like the following (roughly C#
                          pseudo code):

                          int x = 3;
                          SomeMethod(out x);

                          x can now be mutated by 'SomeMethod' and can have a different value.

                          In a 'way' immutable Python types behave a bit like .NET value types,
                          and mutable types like reference types. As you can see, this analogy
                          breaks down.

                          Michael Foord
                          --
                          Pedestrian accidents can happen in the blink of an eye, changing lives forever. When you're out for a stroll or crossing the street, an unexpected collision

                          Comment

                          • Douglas Alan

                            #28
                            Re: Finding the instance reference of an object

                            Steven D'Aprano <steve@REMOVE-THIS-cybersource.com .auwrites:
                            I understand that Python's object and calling semantics are exactly the
                            same as Emerald (and likely other languages as well), and that both
                            Emerald and Python are explicitly based on those of CLU, as described by
                            by Barbara Liskov in 1979:
                            >
                            "In particular it is not call by value because mutations of
                            arguments performed by the called routine will be visible to the
                            caller. And it is not call by reference because access is not
                            given to the variables of the caller, but merely to certain
                            objects."
                            It is quite true that Python's calling semantics are the same as
                            CLU's, and that CLU called these semantics "call by sharing". It's
                            not quite true that CLU invented these calling semantics, however.
                            They were the calling semantics of Lisp long before CLU existed. I'm
                            not sure that Lisp had a name for it, however. Lisp people tended to
                            refer to all variable assignment as "binding".

                            I agree with those who object to calling the Python/CLU/Lisp calling
                            semantics as either "call by value" or "call by reference", which is
                            why I've been a bit dismayed over the years that the term "call by
                            sharing" hasn't caught on. When this terminology is used, the meaning is
                            quite unambiguous.

                            It should be noted that many other mainstream languages now use call
                            by sharing. It's not at all the least peculiar to Python. Such
                            languages include Java, JavaScript, Ruby, C#, and ActionScript.

                            |>oug

                            Comment

                            • gooberts@gmail.com

                              #29
                              Re: Finding the instance reference of an object

                              On Oct 17, 5:39 pm, Joe Strout <j...@strout.ne twrote:
                              On Oct 17, 2008, at 3:19 PM, Grant Edwards wrote:
                              >
                              And my real point is that this is exactly the same as in every
                              other modern language.
                              >
                              No, it isn't.  In many other languages (C, Pascal, etc.), a
                              "variable" is commonly thought of as a fixed location in memory
                              into which one can put values.  Those values may be references
                              to objects.
                              >
                              Right, though not in languages like C and Pascal that don't HAVE the  
                              notion of objects.  We really ought to stop bringing up those  
                              dinosaurs and instead compare Python to any modern OOP language.
                              >
                               In Python, that's not how it works.  There is no
                              "location in memory" that corresponds to a variable with a
                              particular name the way there is in C or Pascal or Fortran or
                              many other languages.
                              >
                              No?  Is there any way to prove that, without delving into the Python  
                              source itself?
                              >
                              If not, then I think you're talking about an internal implementation  
                              detail.

                              I think this "uncontrive d" example addresses the C/Python difference
                              fairly directly (both were tested):
                              ----------------------------------
                              C:

                              struct {int a;} s1, s2;

                              int main()
                              {
                              s1.a = 1;
                              s2 = s1;

                              printf("s1.a %d s2.a %d\n", s1.a, s2.a);
                              s1.a = 99;
                              printf("s1.a %d s2.a %d\n", s1.a, s2.a);
                              }

                              ----------------------------------
                              Python:

                              class mystruct:
                              pass

                              s1 = mystruct()
                              s1.a = 1
                              s2 = s1

                              print "s1.a %2d s2.a %2d" % (s1.a,s2.a)
                              s1.a = 99
                              print "s1.a %2d s2.a %2d" % (s1.a,s2.a)

                              ---------------
                              C OUTPUT:
                              s1.a 1 s2.a 1
                              s1.a 99 s2.a 1

                              Python OUTPUT:
                              s1.a 1 s2.a 1
                              s1.a 99 s2.a 99

                              Note that in C (or C++) the value of s2.a remains unchanged, because
                              the VALUE of s1 (the contents of the memory where s1 resides) was
                              COPIED to the memory location of s2, and subsequently, only the VALUE
                              of s2.a was changed. In Python, s2.a is "changed" (but not really)
                              because it turns out that s2 is just another name for the object that
                              s1 pointed to.

                              So there is no programatically accessible "location in memory" that
                              corresponds to s1 or s2 in Python. There is only a location in memory
                              that corresponds to the object that s1 is currently pointing to. In C,
                              by contrast, there are definite locations in memory that correspond to
                              both variables s1 and s2, and those locations remain always separate,
                              distinct and unchanged throughout the execution of the program.

                              This is not an "implementa tion detail", it is a fundamental part of
                              each language. As C was an "improvemen t" on assembler, the variable
                              names have always just been aliases for memory locations (or
                              registers). You can see this in the output of any C/C++ compiler.

                              In Python, variables are just names/aliases for *references* to
                              objects, not names for the objects/values themselves. The variable
                              names themselves do not correspond directly to the objects' memory
                              locations. While yes, technically, it is true that those reference
                              values must be stored somewhere in memory, *that* is the
                              implementation detail. But is is not the *locations* of these
                              references (i.e., the locations of the Python *variables*) that are
                              copied around, it is the references themselves (the locations of the
                              Python *objects*) that are copied.
                              All that exists in Python is a name->object mapping.
                              >
                              And what does that name->object mapping consist of?  At some level,  
                              there has to be a memory location that stores the reference to the  
                              object, right?
                              I think this is answered above, but just to drive it home, in Python
                              the memory locations of the variables themselves (an implementation
                              detail), which hold the references to the objects, are inaccessible .
                              In C/C++, by contrast, variable names correspond directly to memory
                              locations and objects, and you can easily find the addresses of
                              variables.

                              In C/C++, if you choose, you may have a variable that is itself a
                              reference/pointer to some other memory/object. In C, we would say that
                              the VALUE of that variable is the memory address of another object.
                              But you can, if you need to, get the address of the pointer variable,
                              which points to the *address* of the other object.

                              In Python, a variable is ONLY EVER a reference to an object. You
                              cannot get the address of a Python variable, only of a Python object.

                              Hope this clears things up.

                              dale

                              Comment

                              • Dale Roberts

                                #30
                                Re: Finding the instance reference of an object

                                On Oct 17, 5:39 pm, Joe Strout <j...@strout.ne twrote:
                                On Oct 17, 2008, at 3:19 PM, Grant Edwards wrote:
                                >
                                And my real point is that this is exactly the same as in every
                                other modern language.
                                >
                                No, it isn't. In many other languages (C, Pascal, etc.), a
                                "variable" is commonly thought of as a fixed location in memory
                                into which one can put values. Those values may be references
                                to objects.
                                >
                                Right, though not in languages like C and Pascal that don't HAVE the
                                notion of objects. We really ought to stop bringing up those
                                dinosaurs and instead compare Python to any modern OOP language.
                                >
                                In Python, that's not how it works. There is no
                                "location in memory" that corresponds to a variable with a
                                particular name the way there is in C or Pascal or Fortran or
                                many other languages.
                                >
                                No? Is there any way to prove that, without delving into the Python
                                source itself?
                                >
                                If not, then I think you're talking about an internal implementation
                                detail.

                                I think this "uncontrive d" example addresses the (C/C++)/Python
                                difference fairly directly.
                                ----------------------------------
                                C:

                                struct {int a;} s1, s2;

                                int main()
                                {
                                s1.a = 1;
                                s2 = s1;

                                printf("s1.a %d s2.a %d\n", s1.a, s2.a);
                                s1.a = 99;
                                printf("s1.a %d s2.a %d\n", s1.a, s2.a);
                                }

                                ----------------------------------
                                Python:

                                class mystruct:
                                pass

                                s1 = mystruct()
                                s1.a = 1
                                s2 = s1

                                print "s1.a %2d s2.a %2d" % (s1.a,s2.a)
                                s1.a = 99
                                print "s1.a %2d s2.a %2d" % (s1.a,s2.a)

                                ---------------
                                C OUTPUT:
                                s1.a 1 s2.a 1
                                s1.a 99 s2.a 1

                                Python OUTPUT:
                                s1.a 1 s2.a 1
                                s1.a 99 s2.a 99

                                Note that in C (or C++) the value of s2.a remains unchanged, because
                                the VALUE of s1 (the contents of the memory where s1 resides) was
                                COPIED to the memory location of s2, and subsequently, only the VALUE
                                of s2.a was changed. In Python, s2.a is "changed" (but not really)
                                because it turns out that s2 is just another name for the object that
                                s1 pointed to.

                                So there is no programatically accessible "location in memory" that
                                corresponds to s1 or s2 in Python. There is only a location in memory
                                that corresponds to the object that s1 is currently pointing to. In C,
                                by contrast, there are definite locations in memory that correspond to
                                both variables s1 and s2, and those locations remain always separate,
                                distinct and unchanged throughout the execution of the program.

                                This is not an "implementa tion detail", it is a fundamental part of
                                each language. As C was an "improvemen t" on assembler, the variable
                                names have always just been aliases for memory locations (or
                                registers). You can see this in the output of any C/C++ compiler.

                                In Python, variables are just names/aliases for *references* to
                                objects, not names for the objects/values themselves. The variable
                                names themselves do not correspond directly to the objects' memory
                                locations. While yes, technically, it is true that those reference
                                values must be stored somewhere in memory, *that* is the
                                implementation detail. But is is not the *locations* of these
                                references (i.e., the locations of the Python *variables*) that are
                                copied around, it is the references themselves (the locations of the
                                Python *objects*) that are copied.
                                All that exists in Python is a name->object mapping.
                                >
                                And what does that name->object mapping consist of? At some level,
                                there has to be a memory location that stores the reference to the
                                object, right?
                                I think this is answered above, but just to drive it home, in Python
                                the memory locations of the variables themselves (an implementation
                                detail), which hold the references to the objects, are inaccessible .
                                In C/C++, by contrast, variable names correspond directly to memory
                                locations and objects, and you can easily find the addresses of
                                variables, and the addresses do not change, although the values can.

                                In C/C++, if you choose, you may have a variable that is itself a
                                reference/pointer to some other memory/object/array. In C, we would
                                say that the VALUE of that variable is the memory address of another
                                object. But you can, if you need to, get the address of the pointer
                                variable, which points to the *address* of the other object.

                                In Python, a variable is ONLY EVER a reference to an object. You
                                cannot get the address of a Python variable, only of a Python object.

                                Hope this clears things up.

                                dale

                                Comment

                                Working...