FAQ
I'm pretty happy that I can copy variables and their value from one
object's namespace to another object's namespace with the same variable
names automatically:

class simpleObject():
pass

a = simpleObject()
b = simpleObject()

a.val1 = 1
a.val2 = 2
b.__dict__.update(a.__dict__)
a.val1 = 'a'
a.val1
'a'
a.val2
2
b.val1
1
b.val2
2

The reason I'm posting this is to ask what to watch out for when doing
this. I've seen vague warnings that I don't really understand, and I'm
hoping someone can enlighten me.

Search Discussions

  • Terry Reedy at Jun 12, 2011 at 2:12 am

    On 6/11/2011 9:32 PM, Andrew Berg wrote:
    I'm pretty happy that I can copy variables and their value from one
    You are copying names and their associations, but not the objects or
    thier values.
    object's namespace to another object's namespace with the same variable
    names automatically:

    class simpleObject():
    pass

    a = simpleObject()
    b = simpleObject()

    a.val1 = 1
    a.val2 = 2
    b.__dict__.update(a.__dict__)
    a.val1 = 'a'
    a.val1
    'a'
    a.val2
    2
    b.val1
    1
    b.val2
    2

    --
    Terry Jan Reedy
  • Andrew Berg at Jun 12, 2011 at 2:21 am

    On 2011.06.11 09:12 PM, Terry Reedy wrote:
    On 6/11/2011 9:32 PM, Andrew Berg wrote:
    I'm pretty happy that I can copy variables and their value from one
    You are copying names and their associations, but not the objects or
    thier values.
    Associations? The update() method copies the values; a.val1 and b.val1
    point to two different places in memory.
  • Ian Kelly at Jun 12, 2011 at 3:08 am

    On Sat, Jun 11, 2011 at 8:21 PM, Andrew Berg wrote:
    On 2011.06.11 09:12 PM, Terry Reedy wrote:
    On 6/11/2011 9:32 PM, Andrew Berg wrote:
    I'm pretty happy that I can copy variables and their value from one
    You are copying names and their associations, but not the objects or
    thier values.
    Associations? The update() method copies the values; a.val1 and b.val1
    point to two different places in memory.
    Incorrect. The names in b will be bound to the same objects as the
    names in a, not to copies of them. For immutable objects such as
    ints, this doesn't matter. For mutable objects such as lists, it can:
    class X(object):
    ... pass
    ...
    a = X()
    b = X()
    a.foo = ['apples']
    b.__dict__.update(a.__dict__)
    a.foo
    ['apples']
    b.foo
    ['apples']
    a.foo.append('oranges')
    a.foo
    ['apples', 'oranges']
    b.foo
    ['apples', 'oranges']

    Cheers,
    Ian
  • Andrew Berg at Jun 12, 2011 at 3:28 am

    On 2011.06.11 10:08 PM, Ian Kelly wrote:
    For immutable objects such as
    ints, this doesn't matter. For mutable objects such as lists, it can:
    Well, that's confusing. How would I make actual copies?
  • Ben Finney at Jun 12, 2011 at 3:40 am

    Andrew Berg <bahamutzero8825 at gmail.com> writes:
    On 2011.06.11 10:08 PM, Ian Kelly wrote:
    For immutable objects such as ints, this doesn't matter. For mutable
    objects such as lists, it can:
    Well, that's confusing.
    It's exactly the same as with an ordinary assignment (?a = b?) in
    Python. You will likely want to work through the Python Tutorial
    <URL:http://docs.python.org/tutorial/> and experiment with the samples
    as you go, in order to ground the Python data model in your mind.
    How would I make actual copies?
    At what level? You can create a new dict or a new list by feeding the
    esiting one to the constructor for the type. Or you can use the various
    methods in the ?copy? module depending on what you want.

    Be aware, though, that most Python code gets by just fine without
    explicitly making copies, and I hardly ever see the ?copy? module
    actually used. Work through the tutorial, understand the data model, and
    work with it to get better results.

    --
    \ ?Give a man a fish, and you'll feed him for a day; give him a |
    `\ religion, and he'll starve to death while praying for a fish.? |
    _o__) ?Anonymous |
    Ben Finney
  • Andrew Berg at Jun 12, 2011 at 4:32 am

    On 2011.06.11 10:40 PM, Ben Finney wrote:
    It's exactly the same as with an ordinary assignment (?a = b?) in
    Python.
    Fair enough.
    How would I make actual copies?
    At what level?
    Level? I just want to be able to create an object b with values from
    dictionary a, and not have changes to a reflect b and vice-versa once b
    is created.
    You can create a new dict or a new list by feeding the
    esiting one to the constructor for the type.
    Not sure what you mean here. I thought you meant it copies a dictionary
    when used as input in an __init__() method, but I tried that in the
    interpreter and a still affects b:
    class testObj():
    ... def __init__(self,input):
    ... self.__dict__.update(input)
    ...
    a = dict(list=['one', 'two'], str='hello')
    b = testObj(a)
    a['list'].append('three')
    a
    {'list': ['one', 'two', 'three'], 'str': 'hello'}
    b.list
    ['one', 'two', 'three']
    Or you can use the various
    methods in the ?copy? module depending on what you want.
    copy.deepcopy() looks appealing, but I don't know what the docs mean by
    "administrative data structures".
    Be aware, though, that most Python code gets by just fine without
    explicitly making copies, and I hardly ever see the ?copy? module
    actually used.
    Now that I think about it, I could probably restrict myself to immutable
    types inside the dictionary without much problem. Was that your point,
    or did you mean something else?
  • Ian Kelly at Jun 12, 2011 at 5:12 am

    On Sat, Jun 11, 2011 at 10:32 PM, Andrew Berg wrote:
    On 2011.06.11 10:40 PM, Ben Finney wrote:
    It's exactly the same as with an ordinary assignment (?a = b?) in
    Python.
    Fair enough.
    How would I make actual copies?
    At what level?
    Level? I just want to be able to create an object b with values from
    dictionary a, and not have changes to a reflect b and vice-versa once b
    is created.
    It sounds like the copy.deepcopy function is what you want:
    from copy import deepcopy
    class X(object): pass
    ...
    a = X()
    a.fruit = ['apples']
    b = deepcopy(a)
    a.fruit
    ['apples']
    b.fruit
    ['apples']
    a.fruit.append('oranges')
    a.fruit
    ['apples', 'oranges']
    b.fruit
    ['apples']

    ?Or you can use the various
    methods in the ?copy? module depending on what you want.
    copy.deepcopy() looks appealing, but I don't know what the docs mean by
    "administrative data structures".
    It just means that you don't always want absolutely everything copied.
    For example:
    class World(object): pass
    ...
    class Actor(object):
    ... def __init__(self, world):
    ... self.world = world
    ...
    class Action(object):
    ... def __init__(self, actor):
    ... self.actor = actor
    ...
    a = Action(Actor(World()))
    b = deepcopy(a)
    a.actor is b.actor
    False
    a.actor.world is b.actor.world
    False

    The intention here is probably that a and b should both be part of the
    same World, but as you can see that is not the case; the World got
    copied along with everything else. Python provides machinery to let
    you avoid deep copying absolutely everything, but it's important to be
    aware of cases like this.

    Cheers,
    Ian
  • Steven D'Aprano at Jun 12, 2011 at 2:13 am

    On Sat, 11 Jun 2011 20:32:37 -0500, Andrew Berg wrote:

    I'm pretty happy that I can copy variables and their value from one
    object's namespace to another object's namespace with the same variable
    names automatically:

    class simpleObject():
    pass

    a = simpleObject()
    b = simpleObject()

    a.val1 = 1
    a.val2 = 2
    b.__dict__.update(a.__dict__)
    [...]

    The reason I'm posting this is to ask what to watch out for when doing
    this. I've seen vague warnings that I don't really understand, and I'm
    hoping someone can enlighten me.
    You are injecting data and code from one object to another. If you don't
    know what you're injecting, bad things could happen. Just like in real
    life :)

    The update method unconditionally replaces any item in the first object
    that matches an item in the second. If it has things you don't want, too
    bad, you'll get them:

    class K(object):
    ... data = "things"
    ... status = "working hard for a living"
    ...
    a = K()
    b = K()
    b.data = "stuff and things" # what you want
    b.status = "leaching off dear old granny" # but not this one

    a.__dict__.update(b.__dict__)
    print(a.status)
    leaching off dear old granny


    So never update from a random object you don't know well.

    A second, more subtle risk: not all objects have a __dict__. But if you
    obey the rule about never updating from arbitrary objects you don't know,
    then you won't be surprised by an object with no __dict__.

    Other than that, using update is a good trick to have in your toolbox.




    --
    Steven
  • Andrew Berg at Jun 12, 2011 at 2:28 am

    On 2011.06.11 09:13 PM, Steven D'Aprano wrote:
    So never update from a random object you don't know well.
    Of course. In the project I'm working on, this will be used in the
    __init__() method of a class that accepts a pair of dictionaries or
    possibly **kwargs (for flexibility and to avoid the very problem of an
    object without a __dict__).
    A second, more subtle risk: not all objects have a __dict__. But if you
    obey the rule about never updating from arbitrary objects you don't know,
    then you won't be surprised by an object with no __dict__.
    What objects don't (other than the obvious ones like strings,
    dictionaries, ints and lists)?
  • Steven D'Aprano at Jun 12, 2011 at 8:47 am

    On Sat, 11 Jun 2011 21:28:40 -0500, Andrew Berg wrote:
    On 2011.06.11 09:13 PM, Steven D'Aprano wrote:

    A second, more subtle risk: not all objects have a __dict__. But if you
    obey the rule about never updating from arbitrary objects you don't
    know, then you won't be surprised by an object with no __dict__.
    What objects don't (other than the obvious ones like strings,
    dictionaries, ints and lists)?
    namedtuple is another common example.

    In pure Python, objects created using __slots__ usually don't have a
    __dict__. Quite possibly C extension objects. There may be others.



    --
    Steven
  • Hans Mulder at Jun 12, 2011 at 3:20 pm

    On 12/06/11 10:47:01, Steven D'Aprano wrote:
    On Sat, 11 Jun 2011 21:28:40 -0500, Andrew Berg wrote:
    On 2011.06.11 09:13 PM, Steven D'Aprano wrote:

    A second, more subtle risk: not all objects have a __dict__. But if you
    obey the rule about never updating from arbitrary objects you don't
    know, then you won't be surprised by an object with no __dict__.
    What objects don't (other than the obvious ones like strings,
    dictionaries, ints and lists)?
    namedtuple is another common example.

    In pure Python, objects created using __slots__ usually don't have a
    __dict__. Quite possibly C extension objects. There may be others.
    The base class 'object' is a well-known example:
    ham = object()
    ham.spam = 'eggs'
    Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    AttributeError: 'object' object has no attribute 'spam'
    >>>

    But subclasses of object do have a __dict__ by default,
    which is why you'd normally do:
    class Ham(object):
    ... pass
    ...
    ham = Ham()
    ham.spam = 'eggs'
    >>>

    Here, the only reason for creating a subclass with no visible new
    methods or attributes, is the unmentioned __dict__ attribute that
    Ham instances have and 'object' instances lack.

    -- HansM
  • Tim Chase at Jun 12, 2011 at 10:57 am

    On 06/11/2011 08:32 PM, Andrew Berg wrote:
    I'm pretty happy that I can copy variables and their value from one
    object's namespace to another object's namespace with the same variable
    names automatically:

    b.__dict__.update(a.__dict__)

    The reason I'm posting this is to ask what to watch out for when doing
    this. I've seen vague warnings that I don't really understand, and I'm
    hoping someone can enlighten me.
    I guess the summary is is "it does *exactly* what an Python
    experienced programmer would expect it to, so if things break you
    get to keep both pieces" (which even nicely summarizes Steven's
    sub-thread about objects lacking __dict__). Based on your
    reactions to the replies, I'd say you're sufficiently experienced
    in Python to have your expectations align with Python reality.

    -tkc

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
grouppython-list @
categoriespython
postedJun 12, '11 at 1:32a
activeJun 12, '11 at 3:20p
posts13
users7
websitepython.org

People

Translate

site design / logo © 2022 Grokbase