[Python-ideas] easy thread-safety [was: fork]

Steven D'Aprano steve at pearwood.info
Fri Aug 21 04:57:11 CEST 2015


On Thu, Aug 20, 2015 at 04:02:52PM -0400, Ron Adam wrote:

> The semantics is to have a way to make names (for mutable objects) in 
> outer scopes not be visible to function defined in inner scopes.

Why would you want that? This is a serious question -- there is already 
an easy way to ensure that two functions can't see the other's 
variables: *don't* nest them. The reason for nesting them is to ensure 
that the inner function *can* see the outer's variables. That's the 
whole point of nesting.

So instead of this:
 
>   def foo(x):
>       """ Example of hiding a mutable object from inner scopes. """
>       mutable items
>       items = [1, 2, 3]
>       def bar(y):
>       """ can't see items here. So can't mutate it."""
>           return -y
>       return [bar(y)+x for y in items]

we can write this, with no new keyword, and it will work today:

    def foo(x):
        items = [1, 2, 3]
        return [bar(y)+x for y in items]

    def bar(y):
        """can't see items here. So can't mutate it."""
        return -y

The only reason to nest bar inside foo is if you want bar to have access 
to foo's namespace. 


> So foo is able to protect items from being mutated by functions defined 
> in it's scope.

But functions defined inside foo are under foo's control. They are part 
of foo. foo can mutate items, say by calling items.append(1); why do you 
think it matters whether the call to append comes from inside a 
subfunction or not? Either way, it is still inside foo and part of 
foo's responsibility.

The danger comes, not from the inside of foo, but from the outside of 
foo. foo has no way of knowing whether some other function, let's call 
it spam, has access to the *object* items (not the name!) and is 
mutating it. That is a real danger in threaded programming, but your 
proposal does nothing to protect against it. The danger comes from 
shared mutable state, not nested namespaces.


> It may seem like it isn't needed, because you have control over what a 
> function has access too... ie... just don't do that.  But when you have 
> many programmers working on large projects, things can get messy.  And 
> this helps with that, but also helps in the case of threads.

At the point that you're worried about a single function being so 
complicated or big that developers might accidentally mutate a value 
inside that function, worrying about nested functions is superfluous:


def spam(obj):
    obj.mutate()

def foo():
    obj = something_mutable()  # Don't mutate it!    
    def inner():
        obj.mutate()
    # masses of code
    # more masses of code
    # even more code still
    obj.mutate()  # No protection offered against this
    spam(obj)  # or this
    inner()  # but this is protected against


Why bother singling out such an unlikely and specific source of 
problems?



-- 
Steve


More information about the Python-ideas mailing list