They are always passed the same way. (This way is sometimes called "call-by-object" and sometimes called "call by value where the value is a reference". You can look it up in other questions on here.) The difference is in what the two objects are and what you are doing to them.
p += 1 essentially tells the p object to do += 1 on itself, and then assigns the result to the variable p. Integers cannot change their value, so all this does is add one to p and assign the result to p. p is a "bare name" (i.e., just a plain variable), so this just binds the number 43 to the variable p and that's it.
q.q += 1 tells q.q to do += 1on itself, and assigns the result to q.q. Again integers cannot change their value, so this adds one to q.q. But q.q is not a bare name; it is an attribute reference. So "assigning to q.q" means "ask the object q to assign this new value to its q. attribute". Since q can change its value (that is, the values of its attributes, it does).
The bottom line is that you can't assume the difference in your code is because the argument-passing semantics are different in the two cases. The argument-passing works the same. However, the objects you pass are different (one is an integer, and one is a Q), and those objects can handle operations like += in different ways. The discrepancy is not between two kinds of argument passing but between two different ways to handle +=.