pygame - importing GL - very bad...

someone newsboost at gmail.com
Sun Jan 6 07:46:51 EST 2013


On 01/06/2013 12:37 PM, alex23 wrote:
> On Jan 6, 5:49 am, someone <newsbo... at gmail.com> wrote:
>> I thought that python also used "true" pass-by-reference, although I
>> haven't figured out exactly when I have this problem. I can just see
>> that sometimes I get this problem and then I need to copy the variable,
>> if I don't want the original data of the variable to be overwritten...
>
> Generally I find it easier to call variables 'labels' or 'references';
> you're not stashing a value into a slot, you're giving a name to an
> object. So you're never really passing values around, just labels that
> refer to an object.

Ok.

> The confusion kicks in because there are two types of object: mutable
> and immutable. Mutable objects can change, immutable objects cannot.

Yes, I've seen that described before.

> Operations on an immutable object will return a _new_ immutable
> object; the label used in an operation on an immutable object will
> refer to the new object, any other references to the original object
> will continue to refer to the original. Strings, numbers, tuples and
> frozensets are all immutable built-in types.
>
>      >>> a = "alpha"
>      >>> b = a
>      >>> a = a + "bet"
>      >>> a
>      'alphabet'
>      >>> b
>      'alpha'

Ok, I think I knew some of these things, however I didn't think so much 
about them before now.

> With immutable types, you're safe to pass them into a function, act on
> them, and not have references in the outer scope reflect the change:
>
>      >>> def double(x): return x * 2
>      ...
>      >>> a = "alpha"
>      >>> double(a)
>      'alphaalpha'
>      >>> a
>      'alpha'

This is exactly what I've found out happens to me some times. Until now 
I've managed to fix my problems. But it's good to remember this thing 
with immutable vs. mutable types, which was something I didn't think 
much about before. I'll think about this difference in the future, thank 
you.

> Everything else, including user defined objects, tend to be mutable:
>
>      >>> a = dict(foo=1,bar=2)
>      >>> b = a
>      >>> a['foo'] = 99
>      >>> a
>      {'foo': 99, 'bar': 2}
>      >>> b
>      {'foo': 99, 'bar': 2}

Yes, I've noticed this a lot of times in my own coding...

> With mutable objects, you're _always_ operating on the _same_ object
> that everything is referring to, even when you pass it into a
> different scope:
>
>      >>> def toggle_foo( x ): x['foo'] = not x['foo']
>      ...
>      >>> a = dict(foo=True)
>      >>> toggle_foo(a)
>      >>> a
>      {'foo': False}

Exactly, what I've also experienced a few times.

> Note that the `toggle_foo` function doesn't return anything, nor is
> the value of a re-assigned. The object that a refers to is passed into
> `toggle_foo`, modified in place, and all references to it remain
> pointing to the same, now modified object.

Yes, I notice that, thanks.

> This is one of the big causes of unexpected behaviour to new Python
> users, but as you get a better understanding of how Python's object
> model works, you'll see it's really quite consistent and predictable.

It was a bit surprising to me in the beginning - though I'm still a 
beginner (or maybe now almost an "intermediate" user), the good 
explanation you come with now wasn't something I've thought so much of 
before now. But I've clearly experienced many of the examples you write 
about here, in my own coding and I've usually been very careful about 
checking if my original object was modified un-intentionally. I think I 
can deal with this now.

> There are a couple of ways you can ensure you're always working with a
> copy of an object if you need to. For lists, the canonical way is:
>
>      >>> a = [1,2,3]
>      >>> b = a
>      >>> a = [1, 2, 3]
>      >>> b = a[:] # shallow copy of a
>      >>> b.append(99)
>      >>> b
>      [1, 2, 3, 99]
>      >>> a
>      [1, 2, 3]
>
> `b = a[:]` uses slice notation to create a new list that contains
> everything in the original list, from start to end. This is called a
> "shallow" copy; `a` and `b` both refer to _different_ lists, but the
> objects within are the _same_ objects. For numbers, this isn't

Ok, good to know.

> important, as they're immutable. For mutable objects, however, it's
> something you need to bear in mind:
>
>      >>> a = [ [1,2], [3, 4] ] # list of lists
>      >>> b = a[:]
>      >>> b[0][0] = 99
>      >>> b
>      [[99, 2], [3, 4]]
>      >>> a
>      [[99, 2], [3, 4]]
>
> So here, while `b` refers to copy of `a`, that copy contains the
> _same_ list objects that `a` does, so any changes to the internal
> lists will be reflected in both references, while any changes to `b`
> itself won't be:
>
>      >>> b.append([5,6])
>      >>> b
>      [[99, 2], [3, 4], [5, 6]]
>      >>> a
>      [[99, 2], [3, 4]]

Yes, I've experienced this kind of thing before - but it's a very very 
good explanation you give me know. It makes me understand the problem 
much better, next time I experience it...

> This is where the `copy` module comes to the rescue, providing a
> shallow copy function `copy`, as well as `deepcopy` that makes copies
> of all the objects within the object:
>
>      >>> import copy
>      >>> a = [ [1,2], [3, 4] ] # list of lists
>      >>> b = copy.deepcopy(a)
>      >>> b[0][0] = 99
>      >>> b
>      [[99, 2], [3, 4]]
>      >>> a
>      [[1, 2], [3, 4]]
>
> If you plan on using the `copy` module, it's worthwhile readings it
> docs, as there are some nuances to it that I'm glossing over here.
> TBH, I don't recall every needing to use `copy` in my code.

I almost had to use this "copy.deepcopy" the other day, but I googled 
for it and then I found a way to avoid it...

> Hope this helps bring consistency where you currently find confusion :)

Yes, this is a VERY very good explanation. I was a bit confused about 
when I created my own user defined objects, but now you explained that 
these tend to be mutable which is also my experience.

I'll still keep an extra eye out for this special way of sending objects 
back and forward between function, in order to un-intentionally 
overwrite some data...

Thanks you very much for a very good and precise description of this 
phenomena of the python-language (or what I should call it) :-)





More information about the Python-list mailing list