Reputation: 3
I am still in the early stages of learning Python and came accross this syntax but I have no idea what it does.
check, expression = expression, expression.replace('()', '').replace('[]', '').replace('{}', '')
Now I know what the str.replace() function does, I am just unclear in how in the end is "check" being assigned to this concatenation of replace functions.
Context:
Here is the full code for context, the purpose of it is just to check wether brackets are being used correctly in a given string:
BRACKETS = ("{","[","(","}","]",")")
list = []
#Creating a list with only the brackets in it.
for c in expression:
if (c in BRACKETS) and (c in expression):
list.append(c)
expression = ''.join(list)
while expression:
check, expression = expression, expression.replace('()', '').replace('[]', '').replace('{}', '')
if expression == check:
return False
return True
Upvotes: 0
Views: 88
Reputation: 9010
Consider the following example:
a = 'a'
b = 'b'
temp = a
a = b
b = temp
print(a) # 'b'
print(b) # 'a'
From this, it can be seen that the three lines in the middle swap the values of a
and b
. In Python, tuple packing and unpacking can be used in order to eliminate the need for the temporary variable.
a = 'a'
b = 'b'
temp_tuple = b, a # tuple packing
print(temp_tuple) # ('b', 'a')
a, b = temp_tuple # tuple unpacking
print(a) # 'b'
print(b) # 'a'
Now, we can combine this packing and unpacking into a single expression.
a = 'a'
b = 'b'
a, b = b, a
print(a) # 'b'
print(b) # 'a'
You code saves the original value of expression
into check
and saves the updated version of expression
back into expression
. It then compares the two variables to see whether expression
was changed by all the replace
calls.
Edit: Regarding the comment about whether Python goes through the code segment three times, we can use to dis
module to disassemble the Python bytecode for a test function.
from dis import dis
def test(expression):
while expression:
check, expression = expression, expression.replace('()', '').replace('[]', '').replace('{}', '')
if expression == check:
return False
return True
print dis(test)
This prints the following (with some annotations):
# while expression:
4 0 SETUP_LOOP 75 (to 78)
>> 3 LOAD_FAST 0 (expression) # start
6 POP_JUMP_IF_FALSE 77 # jump to exit
# check, expression = [...]
5 9 LOAD_FAST 0 (expression)
12 LOAD_FAST 0 (expression)
15 LOAD_ATTR 0 (replace)
18 LOAD_CONST 1 ('()')
21 LOAD_CONST 2 ('')
24 CALL_FUNCTION 2
27 LOAD_ATTR 0 (replace)
30 LOAD_CONST 3 ('[]')
33 LOAD_CONST 2 ('')
36 CALL_FUNCTION 2
39 LOAD_ATTR 0 (replace)
42 LOAD_CONST 4 ('{}')
45 LOAD_CONST 2 ('')
48 CALL_FUNCTION 2
51 ROT_TWO
52 STORE_FAST 1 (check)
55 STORE_FAST 0 (expression)
# if check == expression:
6 58 LOAD_FAST 0 (expression)
61 LOAD_FAST 1 (check)
64 COMPARE_OP 2 (==)
67 POP_JUMP_IF_FALSE 3 # jump to start
# return False
7 70 LOAD_GLOBAL 1 (False)
73 RETURN_VALUE
74 JUMP_ABSOLUTE 3 # jump to start
>> 77 POP_BLOCK # exit
# return True
8 >> 78 LOAD_GLOBAL 2 (True)
81 RETURN_VALUE
From this it can be seen that the following occurs:
expression
is loaded and checked for its truthiness. If True
, the loop immediately exits.check
and expression
are loaded, updated, swapped, and stored.check
is compared to that of expression
. If False
, the loop jumps to the start. Otherwise, False
is returned.True
is returned. This will only occur if the loop exited because the value of expression
was not truthy in the first step.I think that the only real thing to note in the check, expression = [...]
line is the use of the instruction ROT_TWO
, which swaps the two top-most stack items. On line 9, the value of expression
is loaded. On lines 12-48, the value of expression
loaded and updated, pushing the value loaded on line 9 back in the stack. Then, on line 51, these two values are swapped.
Upvotes: 1
Reputation: 184161
The line you're asking about is equivalent to:
check = expression
expression = expression.replace('()', '').replace('[]', '').replace('{}', '')
Python allows multiple assignments with a single =
. Each variable on the left side is assigned a corresponding value from the right side.
Upvotes: 1
Reputation: 48067
Explanation
For example:
x, y = 1, 2
x
will be initialized with 1 & y
be initialized with 2.
You can also use this to unwrap tuples. For e.g
>>> def foo(): return 1, 2
>>> x = foo()
>>> x # It is tuple
(1, 2)
>>> x, y = foo() # Value of 'x' is 1 and 'y' is 2
>>> x
1
>>> y
2
You can also use this to swap two numbers as a, b = b, a
Upvotes: 0