This article is written by yingyu Lou, a little sister in the learning group. Her previous post, “What Do I Talk about when Talking about Iterators?” “Received great acclaim. Again, this article compares C++ with Python to explore the most important concepts in programming languages. I wish you all success in your reading!
The sakura rain floor | authorship
Pea flower cat | edited a polished
This article was originally published on Python Cat. Please do not reprint it without permission.
The original address: mp.weixin.qq.com/s/k0VNL6uyv…
0 the introduction
Pointer is a very core and important concept in C, C++, Java, Go and other languages, and Reference is an equally important concept constructed on the basis of Pointers.
Pointers are a necessary and important part of any programming language, and while Python is deliberately vague and limited about the concept of Pointers, Pointers are a topic that must be discussed in depth in Python.
Based on C++ and Python, this article discusses some of Python’s behavior related to Pointers and references.
1 What is a pointer? Why do WE need Pointers?
Pointers have two meanings:
(1) A pointer type that refers to a data type, such as an integer pointer type or a pointer pointer type
(2) refers to a class of variables containing memory addresses, that is, pointer variables
The two meanings of a pointer are closely related: as a variable, a pointer is a way of getting a memory address ready for accessing the value at that address; As a type, this determines the correct offset length of the memory address, which should be equal to the unit memory size of the current type.
If a pointer lacks a pointer type (void *), then the memory address is only a starting address, and the pointer will refuse to solve the pointer because it cannot know the offset from the starting point. If a pointer lacks an address, nullptr, it cannot read memory at that location at all.
The significance of the existence of Pointers is mainly as follows:
- Carries the dynamic memory obtained through malloc, new, and Allocator
- Makes pass-by-pointer possible
The benefits of pass-by-pointer include but are not limited to:
- Avoid meaningless value copy of arguments, greatly improving efficiency
- The ability to modify a variable is not limited to the scope of the variable itself
- The operation of swap, move constructor, move assignment can only operate on Pointers inside the data structure, thus avoiding the overall memory operation on temporary objects, moved sources and other objects
Thus, all operations related to Pointers are necessary or important for programming.
2 references in C++
In C++, references have similar properties to Pointers, but are more invisible and strict. C++ references fall into two categories:
2.1 Lvalue references
An lvalue reference is bound to an lvalue during its initialization phase, and there is no rebinding.
An lvalue reference has almost the same properties as the bound lvalue, the only difference being the decltype declaration:
int numA = 0, &lrefA = numA; // Binding an lvalue
cout << ++lrefA << endl; // Use the lvalue reference as lvalue & rvalue
decltype(lrefA) numB = 1; // Error!
Copy the code
Lvalue references are often used with pass-by-reference:
void swap(int &numA, int &numB)
{
int tmpNum = numA;
numA = numB;
numB = tmpNum;
}
int main(a)
{
int numA = 1, numB = 2;
swap(numA, numB);
cout << numA << endl << numB << endl; 1 / / 2
}
Copy the code
2.2 Rvalue reference
An rvalue reference is bound to an rvalue during its initialization phase and is often used for move constructors and move assignment operations. In these cases, the move constructors and move assignments take over the moved object via rvalue references.
Rvalue references are irrelevant to this article, so I won’t go into detail here.
3 References in Python
3.1 Python does not have references
As the discussion above shows, while “reference” is a very common term for Python, it is clearly inaccurate — there are no lvalue references, let alone rvalue references, because Python does not bind left/rvalue operations.
3.2 Pointer manipulation in Python
It’s not hard to see that, although Python has no references, there is a high degree of similarity between the behavior of variables and the behavior of Pointers in the following aspects:
- In any case (assignment, argument passing, etc.) there is no explicit copy of the value, and when this happens, only one reference count is added
- Variables can be rebound (corresponding to a pointer with no top-level const)
- In some cases (discussed in more detail below), the original values can be modified by function arguments
As you can see, Python variables are more like (sort of crippled) pointer variables than reference variables.
3.2.1 Constructor returns a pointer
There is a very common phrase for Python descriptions: “Everything is an object.”
But there is one important fact that is often overlooked in this sentence: an object is a value, not a pointer or reference.
Therefore, the correct description of the sentence should be: “Everything is a pointer.” Although the revised description is abstract, it is more accurate.
Since objects come from constructors, we know that Python’s constructors construct anonymous objects and return a pointer to that object.
This is Python’s first important connection to Pointers.
Described in code, for Python code:
sampleNum = 0
Copy the code
It is not similar to C++ code:
int sampleNum = 0;
Copy the code
It’s more like:
int __tmpNum = 0, *sampleNum = &__tmpNum;
/ / or:
shared_ptr<int> sampleNum(new int(0));
Copy the code
3.2.2 the __setitems__ operation implicitly resolves the pointer
Another important connection Python has with Pointers is Python’s implicit pointer resolution behavior.
Although Python does not have explicit dereference operations, the (and only) __setitems__ operations implicitly dereference, and modifying a variable through this method is equivalent to modifying the original value of a variable through dereference operations.
This property implies:
- Any operation that does not involve __setitems__ will become pointer rebinding.
For Python code:
numList = [None] * 10
# Rebinding
numList = [None] * 5
Copy the code
Equivalent to:
int *numList = new int[10];
// Rebinding
delete[] numList;
numList = new int[5];
delete[] numList;
Copy the code
Thus, the non-__setitems__ operation on numList causes numList to be bound to a new pointer.
- Any operation involving __setitems__ will be a de-pointer operation.
Due to Python’s heavy reliance on hash tables, “operations involving __setitems__” are actually a very broad behavior in Python, which includes:
- An index operation on an array
- Lookup operations on hash tables
- Operations involving __setattr__ (since Python stores attributes in hash tables, __setattr__ operations will end up being some kind of __setitems__ operation)
Let’s use a slightly more complicated example to illustrate this:
For the following Python code:
class Complex(object):
def __init__(self, real = 0., imag = 0.):
self.real = real
self.imag = imag
def __repr__(self):
return '(%.2f, %.2f)' % (self.real, self.imag)
def main(a):
complexObj = Complex(1..2.)
complexObj.real += 1
complexObj.imag += 1
# (2.00, 3.00)
print(complexObj)
if __name__ == '__main__':
main()
Copy the code
Equivalent to:
class Complex
{
public:
double real, imag;
Complex(double _real = 0..double _imag = 0.): real(_real), imag(_imag) {}
};
ostream &operator<<(ostream &os, const Complex &complexObj)
{
return os << "(" << complexObj.real << "," << complexObj.imag << ")";
}
int main(a)
{
Complex *complexObj = new Complex(1..2.);
complexObj->real++;
complexObj->imag++;
cout << *complexObj << endl;
delete complexObj;
return 0;
}
Copy the code
As you can see, both simple Python types like int and float and our own custom classes behave like we use new to construct objects and return Pointers.
And anything in Python that involves “. The operations on and [] are similar to the “->” or “*” operations on Pointers.
4 afterword.
This article explores the relationship between Python variables and Pointers and references, mainly arguing that “Python does not have references” and that “Python variables behave like some kind of incomplete pointer”.
All opinions are the author’s own. If there are any errors, please correct them.
The public account “Python Cat”, this serial quality articles, cat philosophy series, Python advanced series, good books recommended series, technical writing, quality English recommended and translation, etc., welcome to pay attention to oh.