Note that in p1, you are not assigning a value to list1, which is the name of a variable local to p1. You are actually assigning to the first element of the list object referenced by list1, which is the same list object referenced by li in the enclosing scope.
In p2, on the other hand, i+=10 does assign a value to the local variable i, not the variable int1 in the enclosing scope. This is because the += operator on objects of type int do not actually modify the object, but return a new object instead. (That is, for an int, i+=10 is equivalent to i = i + 10.)
Just to show that += can operate on the underlying object directly, consider this function:
def p3(list1):
list1 += [10]
Then run it on a list:
>>> foo = [1,2,3]
>>> p3(list1)
>>> foo
[1, 2, 3, 10]
Here, the call list1 += [10] is really equivalent to list1.extend([10]), not list1 = list1 + [10], due to how list.__iadd__ is defined. Here, you are again not assigning a value to the name list1, but rather invoking a method on the object referenced by list1 (which is the same object referenced by foo).
(Update: as pointed out by user2357112, technically you do assign to list1, but list.__iadd__ is designed to properly assign the same list back, so that the end result is that you still have a reference to the same mutable object you started with.)