There is disagreement on terminology here. In the Java community, they say that everything is passed by value: primitives are passed by value; references are passed by value. (Just search this site for Java and pass by reference if you don't believe this.) Note that "objects" are not values in the language; only references to objects are.
The distinction that they use is that, in Java, when you pass a reference, the original reference variable in the caller's scope can never be changed (i.e. made to point to a different object) by the callee, which should be possible in pass by reference. Only the object pointed to by the reference may be mutated, but that is irrelevant.
Python values work the exact same way as references in Java. If we use the same definition, then we would say that everything in Python is a reference, and everything is passed by value. Of course, some in the Python community use a different definition.
The disagreement on terminology is the source of most of the confusion.
Since you mention C++, the Python code you have would be equivalent to something like this in C++:
void foo(const int *num) {
num = new int(*num * 2);
}
const int *a = new int(4);
foo(a);
print(a);
Note that the argument is a pointer, which is most similar to references in Java and Python.