杰瑞科技汇

Python指针如何用byref实现参数传递?

Of course! This is a very common point of confusion for developers coming to Python from languages like C, C++, or C#.

Python指针如何用byref实现参数传递?-图1
(图片来源网络,侵删)

Let's break down the concept of pointers and "pass by reference" in Python.

The Short Answer

Python does not have explicit pointers or a & (address-of) operator like C/C++. You cannot get the memory address of a variable and manipulate it directly.

However, Python's function calling behavior is often described as "pass by object reference" or "pass by assignment". This means you are passing a reference to an object, not the object itself or a pointer to it.

This leads to the behavior you're likely looking for: you can modify a mutable object (like a list or dictionary) inside a function, and the change will be reflected outside the function.

Python指针如何用byref实现参数传递?-图2
(图片来源网络,侵删)

Detailed Explanation: "Pass by Object Reference"

To understand this, you need to think about Python variables differently than in C/C++.

  1. Everything is an Object: In Python, integers, strings, lists, functions, etc., are all objects. They live in memory and have a unique identity (their memory address).
  2. Variables are Names (Labels): A variable name, like my_list, is not a "box" holding a value. It's a label or a name that points to an object in memory.

Let's visualize this:

# In memory, there is a list object: [1, 2, 3]
# The variable 'my_list' is a name that refers to it.
my_list = [1, 2, 3]
# The id() function returns the unique memory address of an object.
print(f"ID of my_list: {id(my_list)}")
# Output: ID of my_list: 140123456789123 (example address)

Now, what happens when you pass my_list to a function?

def modify_list_function(input_list):
    print(f"ID inside function (at start): {id(input_list)}")
    # This line does NOT create a new list. It modifies the existing list
    # that 'input_list' and 'my_list' both refer to.
    input_list.append(4)
    print(f"ID inside function (after append): {id(input_list)}")
my_list = [1, 2, 3]
print(f"ID before function call: {id(my_list)}")
modify_list_function(my_list)
print(f"ID after function call: {id(my_list)}")
print(f"my_list is now: {my_list}")

Output:

Python指针如何用byref实现参数传递?-图3
(图片来源网络,侵删)
ID before function call: 140123456789123
ID inside function (at start): 140123456789123  <-- Same ID!
ID inside function (after append): 140123456789123 <-- Still the same ID!
my_list is now: [1, 2, 3, 4]

Why did this work?

  • When you call modify_list_function(my_list), you are passing the reference (the memory address) of the [1, 2, 3] list object.
  • Inside the function, the parameter input_list becomes a new name for that exact same object.
  • When you call input_list.append(4), you are telling the object at that memory address to change itself. Both my_list and input_list are labels for the same, now-modified, object.

The Crucial Distinction: Mutable vs. Immutable Objects

This is where the "pass by object reference" model becomes critical. The behavior changes depending on whether the object is mutable (can be changed) or immutable (cannot be changed).

Mutable Objects (Can be changed "in-place")

  • Examples: list, dict, set
  • Behavior: Changes made inside the function affect the original object.
def add_item(my_dict, key, value):
    # Modifying the dictionary passed in
    my_dict[key] = value
my_data = {'a': 1}
print(f"Before: {my_data}")
add_item(my_data, 'b', 2)
print(f"After: {my_data}")

Output:

Before: {'a': 1}
After: {'a': 1, 'b': 2}

The original my_data dictionary was modified.

Immutable Objects (Cannot be changed "in-place")

  • Examples: int, float, str, tuple
  • Behavior: You cannot change the object itself. If you try to "modify" it, you are actually creating a new object and reassigning the local variable to point to this new object. The original object outside the function is untouched.
def increment_number(x):
    # x is a reference to the integer object 10.
    # Integers are immutable. You can't change the '10' object.
    # So, this line creates a NEW integer object (11) and
    # makes the local variable 'x' point to it.
    x = x + 1
    print(f"Inside function, x is now: {x} (ID: {id(x)})")
my_num = 10
print(f"Before, my_num is: {my_num} (ID: {id(my_num)})")
increment_number(my_num)
print(f"After, my_num is: {my_num} (ID: {id(my_num)})")

Output:

Before, my_num is: 10 (ID: 140123456789456)
Inside function, x is now: 11 (ID: 140123456789480) <-- Different ID!
After, my_num is: 10 (ID: 140123456789456)     <-- Unchanged!

Why didn't this work?

  1. my_num is a label for the integer object 10.
  2. The function receives a reference to 10 and assigns it to its local variable x. Now, my_num and x both point to 10.
  3. x = x + 1 cannot change the 10 object. It creates a new integer object, 11.
  4. The local variable x is then updated to point to this new 11 object.
  5. The variable my_num in the outer scope still points to the original, unchanged 10 object.

How to Simulate "Pass by Reference" for Immutable Objects?

What if you want to change an immutable object (like an integer) and have the change reflected outside? You can't do it directly. You have to return the new value and assign it back.

This is the Pythonic way to handle it.

def increment_and_return(x):
    # Create a new value
    new_x = x + 1
    return new_x
my_num = 10
print(f"Before: {my_num}")
# You must assign the returned value back to the variable
my_num = increment_and_return(my_num)
print(f"After: {my_num}")

Output:

Before: 10
After: 11

Summary Table

Feature C/C++ (Pointers) Python
Pointer Concept Explicit. A variable that stores a memory address. Implicit. All variables are references to objects.
& (address-of) int* p = &my_int; No & operator. Use id(my_var) to see the address.
(dereference) int val = *p; *No `operator for dereferencing.** Access is implicit (val = p`).
Passing to Function Can pass by value or by reference. Always "pass by object reference".
Mutable Objects Changes inside function affect original. Changes inside function affect original.
Immutable Objects Changes inside function affect original (if passed by reference). Changes inside function do not affect original. A new object is created.

Conclusion

You don't need pointers in Python to achieve the goals you might have with them. The key is to understand the difference between mutable and immutable objects and how Python's "pass by object reference" model works.

  • To modify a list or dict inside a function, just pass it in. The changes will be visible outside.
  • To modify an int or str inside a function, you must return the new value and assign it back to the original variable.
分享:
扫描分享到社交APP
上一篇
下一篇