Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #93044 > unrolled thread

method returns object reference

Started byTim <jtim.arnold@gmail.com>
First post2015-06-23 11:32 -0700
Last post2015-06-23 13:59 -0700
Articles 3 — 3 participants

Back to article view | Back to comp.lang.python


Contents

  method returns object reference Tim <jtim.arnold@gmail.com> - 2015-06-23 11:32 -0700
    Re: method returns object reference Ian Kelly <ian.g.kelly@gmail.com> - 2015-06-23 13:30 -0600
    Re: method returns object reference Ned Batchelder <ned@nedbatchelder.com> - 2015-06-23 13:59 -0700

#93044 — method returns object reference

FromTim <jtim.arnold@gmail.com>
Date2015-06-23 11:32 -0700
Subjectmethod returns object reference
Message-ID<109aafce-613c-4d6c-9f78-4bbe424f5901@googlegroups.com>
I spent a while finding this problem which looks something like the old "mutable default argument" problem. http://docs.python-guide.org/en/latest/writing/gotchas/#mutable-default-arguments

I'm not crystal clear on the details, but once I found it, the fix was easy.
I'm posting here just because I thought it was interesting.

The situation is that I have a Worker() which has a Client(). 
The worker queries the client; client returns its self.response
worker manipulates that response. Now client's response has same changes.

The code below prints the following two lines, showing how the 'newkey' is now inside the Client response, even though it was set in the worker.  This must be bad practice!  In my real code, the response is no longer an instance variable, which fixed the problem. It never had any business being bound to the client anyway.

output:
[('text', 'first thing')]
[('text', 'second thing'), ('newkey', 'my new value')]
 

class Client(object):
    def __init__(self):
        self.response = dict()

    def query(self, text):
        self.response['text'] = text
        print self.response.items()
        return self.response


class Worker(object):
    def __init__(self):
        self.client = Client()

    def work(self, expression):
        data = self.client.query(expression)
        data['newkey'] = 'my new value'


if __name__ == '__main__':
    t = Worker()
    t.work('first thing')
    t.work('second thing')

[toc] | [next] | [standalone]


#93046

FromIan Kelly <ian.g.kelly@gmail.com>
Date2015-06-23 13:30 -0600
Message-ID<mailman.732.1435087895.13271.python-list@python.org>
In reply to#93044
On Tue, Jun 23, 2015 at 12:32 PM, Tim <jtim.arnold@gmail.com> wrote:
> The code below prints the following two lines, showing how the 'newkey' is now inside the Client response, even though it was set in the worker.  This must be bad practice!  In my real code, the response is no longer an instance variable, which fixed the problem. It never had any business being bound to the client anyway.

I agree. There may be reasons why the client would want to hold onto
the response, e.g. caching, but there are none evident in the code you
posted. What it *shouldn't* do if it's going to hold on to state like
that is share it with external code without at least a contract
defining allowed mutations. If the consumer can't reasonably be
expected not to modify the shared state, then it should be copied, not
shared.

[toc] | [prev] | [next] | [standalone]


#93051

FromNed Batchelder <ned@nedbatchelder.com>
Date2015-06-23 13:59 -0700
Message-ID<99d81f4b-fbdb-4309-9bd7-f278e0119079@googlegroups.com>
In reply to#93044
On Tuesday, June 23, 2015 at 2:32:55 PM UTC-4, Tim wrote:
> I spent a while finding this problem which looks something like the old "mutable default argument" problem. http://docs.python-guide.org/en/latest/writing/gotchas/#mutable-default-arguments
> 
> I'm not crystal clear on the details, but once I found it, the fix was easy.
> I'm posting here just because I thought it was interesting.
> 
> The situation is that I have a Worker() which has a Client(). 
> The worker queries the client; client returns its self.response
> worker manipulates that response. Now client's response has same changes.

Assignment in Python never makes a copy, it only makes a new name refer to
an existing value.  This talk covers the details in depth:

    http://nedbatchelder.com/text/names1.html

--Ned.

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.python


csiph-web