A lot is happening on this line:
sum((img_1 == 0)[img_2 == 0])
first, img_1 == 0 is an operation that returns a numpy array of 1's where imp_1 is not zero, else 0. Try to print it to have a look. This array does have the save size as img_1. The operation in the brackets is basically the same operation with img_2.
Here, there are 1's (equivalent to True) where there are 0's in a1:
a1 = np.arange(2*3).reshape(2, 3)
# array([[0, 1, 2],
# [3, 4, 5]])
a1 == 0
# array([[ True, False, False],
# [False, False, False]])
The parenthesis around img_1 == 0 are only here so that the following indexing operation —materialized by the brackets— apply to the result of img_1 == 0 rather than to the 0 number.. It is not an operation but a mean to group and give priority to some operations (see @hpaulj comment).
The last operation involved —the one materialized by the brackets— is an indexing operation. First note that (img_1 == 0) and img_2 == 0 are the same size (considering that both images are the same size). This operation retrieves only the elements from (img_1 == 0) where there are 0's in img_2. This "selects" elements from an array according to the index specified inside the brackets.
Here there are three 1's in a at different location. The operation retrieves only the elements in a where a == 1 is true, so it returns the three ones:
a = np.array([[1, 2, 1], [3, 1, 4]])
a[a == 1]
# array([1, 1, 1])
This summing operation is not the most understandable form, you can use this one for your 3-image case:
((img1 == 0) & (img2 == 0) & (img3 == 0)).sum()
This reads pretty well: "creates a numpy array of 1's and 0's containing 1's where there are 0's in imag1 AND there are 0's in img2 AND ..., then sum this array".