0

Background

Suppose I have 2 global variables a = [1,2,3] and b = ['a','b'], If I must exchange a and b inside a function, I can do with following code:

a = [1,2,3]
b = ['a','b']
def fun1():
    global a,b
    temp = a[::-1]
    a = b[::-1]
    b = temp
fun1()
print(a,b)

Out:

['b', 'a'] [3, 2, 1]

However, If a and b are parameters of my function, how do we do it?

a = [1,2,3]
b = ['a','b']
def fun2(a,b):
    global a,b
    temp = a[::-1]
    a = b[::-1]
    b = temp
fun2(a,b)
print(a,b)

Raise Error:

SyntaxError: name 'a' is parameter and global

My attempt

I tried to do with exec, it works on Python 3.7, However, it does not work on Codewars 3.6 env. I don't know the reason, maybe I just find wrong method.

a = [1,2,3]
b = ['a','b']
def exchange_with(a, b):
    temp = a[::-1].copy()
    exec('a = b[::-1]',globals())
    exec('b = temp',locals(),globals())
exchange_with(a, b)
a,b

Out:

(['b', 'a'], [3, 2, 1])

3
  • func2(a,b) require 2 args but you don't give any Commented Feb 3, 2020 at 16:17
  • @ErnestBidouille sry for that , I revised Commented Feb 3, 2020 at 16:23
  • 1
    You can't have a variable as an parameter and global you have to choose. It's better not to use global, just delete it. Commented Feb 3, 2020 at 16:26

1 Answer 1

1

You still have to pass the values as arguments. Once inside the function, you need to make in-place slice assignments to each list. No global names need be involved.

def fun2(a,b):
    a[:], b[:] = b[::-1], a[::-1]

x = [1,2,3]
y = ['a', 'b']
fun2(x, y)
assert x == ['b', 'a']
assert y == [3, 2, 1]
Sign up to request clarification or add additional context in comments.

7 Comments

I used to treat a and b inside function body as local variable, which means a inside function body only contains value of global a. However, your method is absolutely right! id of global a == id(a) inside function. I think it is so dangerous that we can revise global variable a without a global a statement. So in practice, better to not change global variables like this?
a and b are local variables, but that doesn't mean they can't refer to values that are also referred to by global variables, which means that if you aren't careful, you can mutate global state using a local variables. (If you haven't already, you may want to read nedbatchelder.com/text/names.html.) In other words, names have scope, but values do not.
@chepner Not OP but thanks for your reply. However, the link you posted doesn't work, care to give it an update? I followed here from your CodeWars answer. My question is: why [:] will make it work when the function is a, b = b[::-1], a[::-1], the global values don't get changed at all? Thanks.
Sorry, the link should be nedbatchelder.com/text/names.html; the end-of-sentence period got included.
a = ... is an ordinary assignment; it makes the name a refer to a new value regardless of what it used to refer to. a[:] = ... isn't "really" an assignment at all; it's implemented by a method call a.__setitem__(slice(None, None, None), ...).
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.