Chuyển thể hiện của lớp sang hàm python

Sau khi làm quen với Python, bạn có thể nhận thấy các trường hợp trong đó các hàm của bạn không sửa đổi các đối số tại chỗ như bạn mong đợi, đặc biệt nếu bạn đã quen thuộc với các ngôn ngữ lập trình khác. Một số ngôn ngữ xử lý các đối số hàm dưới dạng tham chiếu đến các biến hiện có, được gọi là chuyển theo tham chiếu. Các ngôn ngữ khác xử lý chúng như các giá trị độc lập, một cách tiếp cận được gọi là chuyển theo giá trị

Nếu bạn là một lập trình viên Python trung cấp muốn hiểu cách xử lý đối số hàm đặc biệt của Python, thì hướng dẫn này là dành cho bạn. Bạn sẽ triển khai các trường hợp sử dụng thực tế của các cấu trúc chuyển qua tham chiếu trong Python và tìm hiểu một số phương pháp hay nhất để tránh những cạm bẫy với các đối số hàm của bạn

Trong hướng dẫn này, bạn sẽ học

  • Chuyển qua tham chiếu nghĩa là gì và tại sao bạn muốn làm như vậy
  • Chuyển theo tham chiếu khác với cả chuyển theo giá trị và cách tiếp cận độc đáo của Python như thế nào
  • Cách các đối số hàm hoạt động trong Python
  • Cách bạn có thể sử dụng một số loại có thể thay đổi nhất định để chuyển qua tham chiếu trong Python
  • Các phương pháp hay nhất để sao chép thông qua tham chiếu trong Python là gì

Tiền thưởng miễn phí. 5 Suy nghĩ về Làm chủ Python, một khóa học miễn phí dành cho các nhà phát triển Python cho bạn thấy lộ trình và tư duy mà bạn sẽ cần để đưa các kỹ năng Python của mình lên một tầm cao mới

Xác định vượt qua bằng tham chiếu

Trước khi bạn đi sâu vào các chi tiết kỹ thuật của việc chuyển qua tham chiếu, sẽ rất hữu ích nếu bạn xem xét kỹ hơn thuật ngữ này bằng cách chia nhỏ nó thành các thành phần

  • Vượt qua có nghĩa là cung cấp một đối số cho một chức năng
  • Theo tham chiếu có nghĩa là đối số bạn đang chuyển đến hàm là tham chiếu đến một biến đã tồn tại trong bộ nhớ chứ không phải là bản sao độc lập của biến đó

Vì bạn đang cung cấp cho hàm một tham chiếu đến một biến hiện có, nên tất cả các thao tác được thực hiện trên tham chiếu này sẽ ảnh hưởng trực tiếp đến biến mà nó tham chiếu đến. Hãy xem xét một số ví dụ về cách hoạt động của điều này trong thực tế

Dưới đây, bạn sẽ thấy cách truyền biến theo tham chiếu trong C#. Lưu ý việc sử dụng từ khóa

>>> def main():
..     n = 9001
..     print(f"Initial address of n: {id(n)}")
..     increment(n)
..     print(f"  Final address of n: {id(n)}")
...
>>> def increment(x):
..     print(f"Initial address of x: {id(x)}")
..     x += 1
..     print(f"  Final address of x: {id(x)}")
...
>>> main()
Initial address of n: 140562586057840
Initial address of x: 140562586057840
  Final address of x: 140562586057968
  Final address of n: 140562586057840
2 trong các dòng được đánh dấu

using System;

// Source:
// https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/passing-parameters
class Program
{
    static void Main(string[] args)
    {
        int arg;

        // Passing by reference.
        // The value of arg in Main is changed.
        arg = 4;
        squareRef(ref arg);
        Console.WriteLine(arg);
        // Output: 16
    }

    static void squareRef(ref int refParameter)
    {
        refParameter *= refParameter;
    }
}

Như bạn thấy,

>>> def main():
..     n = 9001
..     print(f"Initial address of n: {id(n)}")
..     increment(n)
..     print(f"  Final address of n: {id(n)}")
...
>>> def increment(x):
..     print(f"Initial address of x: {id(x)}")
..     x += 1
..     print(f"  Final address of x: {id(x)}")
...
>>> main()
Initial address of n: 140562586057840
Initial address of x: 140562586057840
  Final address of x: 140562586057968
  Final address of n: 140562586057840
3 của
>>> def main():
..     n = 9001
..     print(f"Initial address of n: {id(n)}")
..     increment(n)
..     print(f"  Final address of n: {id(n)}")
...
>>> def increment(x):
..     print(f"Initial address of x: {id(x)}")
..     x += 1
..     print(f"  Final address of x: {id(x)}")
...
>>> main()
Initial address of n: 140562586057840
Initial address of x: 140562586057840
  Final address of x: 140562586057968
  Final address of n: 140562586057840
4 phải được khai báo bằng từ khóa
>>> def main():
..     n = 9001
..     print(f"Initial address of n: {id(n)}")
..     increment(n)
..     print(f"  Final address of n: {id(n)}")
...
>>> def increment(x):
..     print(f"Initial address of x: {id(x)}")
..     x += 1
..     print(f"  Final address of x: {id(x)}")
...
>>> main()
Initial address of n: 140562586057840
Initial address of x: 140562586057840
  Final address of x: 140562586057968
  Final address of n: 140562586057840
2 và bạn cũng phải sử dụng từ khóa khi gọi hàm. Sau đó, đối số sẽ được chuyển vào theo tham chiếu và có thể được sửa đổi tại chỗ

Python không có từ khóa

>>> def main():
..     n = 9001
..     print(f"Initial address of n: {id(n)}")
..     increment(n)
..     print(f"  Final address of n: {id(n)}")
...
>>> def increment(x):
..     print(f"Initial address of x: {id(x)}")
..     x += 1
..     print(f"  Final address of x: {id(x)}")
...
>>> main()
Initial address of n: 140562586057840
Initial address of x: 140562586057840
  Final address of x: 140562586057968
  Final address of n: 140562586057840
2 hoặc bất kỳ thứ gì tương đương với nó. Nếu bạn cố gắng sao chép ví dụ trên càng giống càng tốt trong Python, thì bạn sẽ thấy kết quả khác

>>>

>>> def main():
..     arg = 4
..     square(arg)
..     print(arg)
...
>>> def square(n):
..     n *= n
...
>>> main()
4

Trong trường hợp này, biến

>>> def main():
..     n = 9001
..     print(f"Initial address of n: {id(n)}")
..     increment(n)
..     print(f"  Final address of n: {id(n)}")
...
>>> def increment(x):
..     print(f"Initial address of x: {id(x)}")
..     x += 1
..     print(f"  Final address of x: {id(x)}")
...
>>> main()
Initial address of n: 140562586057840
Initial address of x: 140562586057840
  Final address of x: 140562586057968
  Final address of n: 140562586057840
7 không bị thay đổi tại chỗ. Có vẻ như Python coi đối số được cung cấp của bạn là một giá trị độc lập thay vì tham chiếu đến một biến hiện có. Điều này có nghĩa là Python chuyển các đối số theo giá trị thay vì theo tham chiếu?

Không hẳn. Python chuyển các đối số không phải theo tham chiếu hay theo giá trị, mà bằng cách gán. Dưới đây, bạn sẽ nhanh chóng khám phá các chi tiết về chuyển giá trị và chuyển tham chiếu trước khi xem xét kỹ hơn cách tiếp cận của Python. Sau đó, bạn sẽ xem qua một số phương pháp hay nhất để đạt được hiệu quả tương đương với việc chuyển qua tham chiếu trong Python

Loại bỏ các quảng cáo

Tương phản Pass by Reference và Pass by Value

Khi bạn chuyển các đối số hàm theo tham chiếu, các đối số đó chỉ là tham chiếu đến các giá trị hiện có. Ngược lại, khi bạn chuyển các đối số theo giá trị, các đối số đó sẽ trở thành bản sao độc lập của các giá trị ban đầu

Hãy xem lại ví dụ C#, lần này không sử dụng từ khóa

>>> def main():
..     n = 9001
..     print(f"Initial address of n: {id(n)}")
..     increment(n)
..     print(f"  Final address of n: {id(n)}")
...
>>> def increment(x):
..     print(f"Initial address of x: {id(x)}")
..     x += 1
..     print(f"  Final address of x: {id(x)}")
...
>>> main()
Initial address of n: 140562586057840
Initial address of x: 140562586057840
  Final address of x: 140562586057968
  Final address of n: 140562586057840
2. Điều này sẽ khiến chương trình sử dụng hành vi mặc định là chuyển theo giá trị

using System;

// Source:
// https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/passing-parameters
class Program
{
    static void Main(string[] args)
    {
        int arg;

        // Passing by value.
        // The value of arg in Main is not changed.
        arg = 4;
        squareVal(arg);
        Console.WriteLine(arg);
        // Output: 4
    }

    static void squareVal(int valParameter)
    {
        valParameter *= valParameter;
    }
}

Ở đây, bạn có thể thấy rằng

>>> def main():
..     n = 9001
..     print(f"Initial address of n: {id(n)}")
..     increment(n)
..     print(f"  Final address of n: {id(n)}")
...
>>> def increment(x):
..     print(f"Initial address of x: {id(x)}")
..     x += 1
..     print(f"  Final address of x: {id(x)}")
...
>>> main()
Initial address of n: 140562586057840
Initial address of x: 140562586057840
  Final address of x: 140562586057968
  Final address of n: 140562586057840
9 không sửa đổi biến ban đầu. Thay vào đó,
using System;

// Source:
// https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/passing-parameters
class Program
{
    static void Main(string[] args)
    {
        int arg;

        // Passing by reference.
        // The value of arg in Main is changed.
        arg = 4;
        squareRef(ref arg);
        Console.WriteLine(arg);
        // Output: 16
    }

    static void squareRef(ref int refParameter)
    {
        refParameter *= refParameter;
    }
}
10 là một bản sao độc lập của biến gốc
>>> def main():
..     n = 9001
..     print(f"Initial address of n: {id(n)}")
..     increment(n)
..     print(f"  Final address of n: {id(n)}")
...
>>> def increment(x):
..     print(f"Initial address of x: {id(x)}")
..     x += 1
..     print(f"  Final address of x: {id(x)}")
...
>>> main()
Initial address of n: 140562586057840
Initial address of x: 140562586057840
  Final address of x: 140562586057968
  Final address of n: 140562586057840
7. Mặc dù điều đó phù hợp với hành vi mà bạn sẽ thấy trong Python, nhưng hãy nhớ rằng Python không truyền chính xác theo giá trị. Hãy chứng minh điều đó

using System;

// Source:
// https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/passing-parameters
class Program
{
    static void Main(string[] args)
    {
        int arg;

        // Passing by reference.
        // The value of arg in Main is changed.
        arg = 4;
        squareRef(ref arg);
        Console.WriteLine(arg);
        // Output: 16
    }

    static void squareRef(ref int refParameter)
    {
        refParameter *= refParameter;
    }
}
12 tích hợp sẵn của Python trả về một số nguyên biểu thị địa chỉ bộ nhớ của đối tượng mong muốn. Sử dụng
using System;

// Source:
// https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/passing-parameters
class Program
{
    static void Main(string[] args)
    {
        int arg;

        // Passing by reference.
        // The value of arg in Main is changed.
        arg = 4;
        squareRef(ref arg);
        Console.WriteLine(arg);
        // Output: 16
    }

    static void squareRef(ref int refParameter)
    {
        refParameter *= refParameter;
    }
}
12, bạn có thể xác minh các xác nhận sau

  1. Các đối số của hàm ban đầu đề cập đến cùng một địa chỉ với các biến ban đầu của chúng
  2. Việc gán lại đối số trong hàm sẽ cung cấp cho nó một địa chỉ mới trong khi biến ban đầu không bị sửa đổi

Trong ví dụ dưới đây, lưu ý rằng địa chỉ của

using System;

// Source:
// https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/passing-parameters
class Program
{
    static void Main(string[] args)
    {
        int arg;

        // Passing by reference.
        // The value of arg in Main is changed.
        arg = 4;
        squareRef(ref arg);
        Console.WriteLine(arg);
        // Output: 16
    }

    static void squareRef(ref int refParameter)
    {
        refParameter *= refParameter;
    }
}
14 ban đầu khớp với địa chỉ của
using System;

// Source:
// https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/passing-parameters
class Program
{
    static void Main(string[] args)
    {
        int arg;

        // Passing by reference.
        // The value of arg in Main is changed.
        arg = 4;
        squareRef(ref arg);
        Console.WriteLine(arg);
        // Output: 16
    }

    static void squareRef(ref int refParameter)
    {
        refParameter *= refParameter;
    }
}
15 nhưng thay đổi sau khi gán lại, trong khi địa chỉ của
using System;

// Source:
// https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/passing-parameters
class Program
{
    static void Main(string[] args)
    {
        int arg;

        // Passing by reference.
        // The value of arg in Main is changed.
        arg = 4;
        squareRef(ref arg);
        Console.WriteLine(arg);
        // Output: 16
    }

    static void squareRef(ref int refParameter)
    {
        refParameter *= refParameter;
    }
}
15 không bao giờ thay đổi

>>>

>>> def main():
..     n = 9001
..     print(f"Initial address of n: {id(n)}")
..     increment(n)
..     print(f"  Final address of n: {id(n)}")
...
>>> def increment(x):
..     print(f"Initial address of x: {id(x)}")
..     x += 1
..     print(f"  Final address of x: {id(x)}")
...
>>> main()
Initial address of n: 140562586057840
Initial address of x: 140562586057840
  Final address of x: 140562586057968
  Final address of n: 140562586057840

Thực tế là các địa chỉ ban đầu của

using System;

// Source:
// https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/passing-parameters
class Program
{
    static void Main(string[] args)
    {
        int arg;

        // Passing by reference.
        // The value of arg in Main is changed.
        arg = 4;
        squareRef(ref arg);
        Console.WriteLine(arg);
        // Output: 16
    }

    static void squareRef(ref int refParameter)
    {
        refParameter *= refParameter;
    }
}
15 và
using System;

// Source:
// https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/passing-parameters
class Program
{
    static void Main(string[] args)
    {
        int arg;

        // Passing by reference.
        // The value of arg in Main is changed.
        arg = 4;
        squareRef(ref arg);
        Console.WriteLine(arg);
        // Output: 16
    }

    static void squareRef(ref int refParameter)
    {
        refParameter *= refParameter;
    }
}
14 giống nhau khi bạn gọi
using System;

// Source:
// https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/passing-parameters
class Program
{
    static void Main(string[] args)
    {
        int arg;

        // Passing by reference.
        // The value of arg in Main is changed.
        arg = 4;
        squareRef(ref arg);
        Console.WriteLine(arg);
        // Output: 16
    }

    static void squareRef(ref int refParameter)
    {
        refParameter *= refParameter;
    }
}
19 chứng tỏ rằng đối số
using System;

// Source:
// https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/passing-parameters
class Program
{
    static void Main(string[] args)
    {
        int arg;

        // Passing by reference.
        // The value of arg in Main is changed.
        arg = 4;
        squareRef(ref arg);
        Console.WriteLine(arg);
        // Output: 16
    }

    static void squareRef(ref int refParameter)
    {
        refParameter *= refParameter;
    }
}
14 không được truyền theo giá trị. Mặt khác,
using System;

// Source:
// https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/passing-parameters
class Program
{
    static void Main(string[] args)
    {
        int arg;

        // Passing by reference.
        // The value of arg in Main is changed.
        arg = 4;
        squareRef(ref arg);
        Console.WriteLine(arg);
        // Output: 16
    }

    static void squareRef(ref int refParameter)
    {
        refParameter *= refParameter;
    }
}
15 và
using System;

// Source:
// https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/passing-parameters
class Program
{
    static void Main(string[] args)
    {
        int arg;

        // Passing by reference.
        // The value of arg in Main is changed.
        arg = 4;
        squareRef(ref arg);
        Console.WriteLine(arg);
        // Output: 16
    }

    static void squareRef(ref int refParameter)
    {
        refParameter *= refParameter;
    }
}
14 sẽ có địa chỉ bộ nhớ riêng biệt

Trước khi bạn tìm hiểu chi tiết về cách Python xử lý các đối số, chúng ta hãy xem xét một số trường hợp sử dụng thực tế của việc chuyển qua tham chiếu

Sử dụng Pass by Reference Constructs

Truyền biến theo tham chiếu là một trong số các chiến lược bạn có thể sử dụng để triển khai các mẫu lập trình nhất định. Mặc dù hiếm khi cần thiết nhưng việc chuyển qua tham chiếu có thể là một công cụ hữu ích

Trong phần này, bạn sẽ xem xét ba trong số các mẫu phổ biến nhất mà chuyển qua tham chiếu là một cách tiếp cận thực tế. Sau đó, bạn sẽ thấy cách bạn có thể triển khai từng mẫu này bằng Python

Tránh các đối tượng trùng lặp

Như bạn đã thấy, việc chuyển một biến theo giá trị sẽ tạo ra một bản sao của giá trị đó và lưu trữ trong bộ nhớ. Trong các ngôn ngữ mặc định chuyển theo giá trị, thay vào đó, bạn có thể thấy lợi ích về hiệu suất khi chuyển biến theo tham chiếu, đặc biệt là khi biến chứa nhiều dữ liệu. Điều này sẽ rõ ràng hơn khi mã của bạn đang chạy trên các máy bị hạn chế về tài nguyên

Tuy nhiên, trong Python, đây không bao giờ là vấn đề. Bạn sẽ thấy lý do tại sao trong phần tiếp theo

Trả về nhiều giá trị

Một trong những ứng dụng phổ biến nhất của việc chuyển qua tham chiếu là tạo một hàm thay đổi giá trị của các tham số tham chiếu trong khi trả về một giá trị khác biệt. Bạn có thể sửa đổi ví dụ C# chuyển qua tham chiếu của mình để minh họa kỹ thuật này

using System;

// Source:
// https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/passing-parameters
class Program
{
    static void Main(string[] args)
    {
        int arg;

        // Passing by reference.
        // The value of arg in Main is changed.
        arg = 4;
        squareRef(ref arg);
        Console.WriteLine(arg);
        // Output: 16
    }

    static void squareRef(ref int refParameter)
    {
        refParameter *= refParameter;
    }
}
1

Trong ví dụ trên,

>>> def main():
..     n = 9001
..     print(f"Initial address of n: {id(n)}")
..     increment(n)
..     print(f"  Final address of n: {id(n)}")
...
>>> def increment(x):
..     print(f"Initial address of x: {id(x)}")
..     x += 1
..     print(f"  Final address of x: {id(x)}")
...
>>> main()
Initial address of n: 140562586057840
Initial address of x: 140562586057840
  Final address of x: 140562586057968
  Final address of n: 140562586057840
63 trả về một chuỗi lời chào và cũng sửa đổi giá trị của
>>> def main():
..     n = 9001
..     print(f"Initial address of n: {id(n)}")
..     increment(n)
..     print(f"  Final address of n: {id(n)}")
...
>>> def increment(x):
..     print(f"Initial address of x: {id(x)}")
..     x += 1
..     print(f"  Final address of x: {id(x)}")
...
>>> main()
Initial address of n: 140562586057840
Initial address of x: 140562586057840
  Final address of x: 140562586057968
  Final address of n: 140562586057840
64. Bây giờ hãy cố gắng tái tạo điều này càng giống càng tốt trong Python

>>>

>>> def main():
..     n = 9001
..     print(f"Initial address of n: {id(n)}")
..     increment(n)
..     print(f"  Final address of n: {id(n)}")
...
>>> def increment(x):
..     print(f"Initial address of x: {id(x)}")
..     x += 1
..     print(f"  Final address of x: {id(x)}")
...
>>> main()
Initial address of n: 140562586057840
Initial address of x: 140562586057840
  Final address of x: 140562586057968
  Final address of n: 140562586057840
6

>>> def main():
..     n = 9001
..     print(f"Initial address of n: {id(n)}")
..     increment(n)
..     print(f"  Final address of n: {id(n)}")
...
>>> def increment(x):
..     print(f"Initial address of x: {id(x)}")
..     x += 1
..     print(f"  Final address of x: {id(x)}")
...
>>> main()
Initial address of n: 140562586057840
Initial address of x: 140562586057840
  Final address of x: 140562586057968
  Final address of n: 140562586057840
64 không tăng lên trong ví dụ trên bởi vì, như bạn đã học trước đây, Python không có cách nào truyền giá trị theo tham chiếu. Vậy làm thế nào bạn có thể đạt được kết quả tương tự như bạn đã làm với C#?

Về bản chất, tham số tham chiếu trong C# cho phép hàm không chỉ trả về giá trị mà còn hoạt động trên các tham số bổ sung. Điều này tương đương với việc trả về nhiều giá trị

May mắn thay, Python đã hỗ trợ trả về nhiều giá trị. Nói một cách chính xác, một hàm Python trả về nhiều giá trị thực sự trả về một bộ chứa mỗi giá trị

>>>

>>> def main():
..     n = 9001
..     print(f"Initial address of n: {id(n)}")
..     increment(n)
..     print(f"  Final address of n: {id(n)}")
...
>>> def increment(x):
..     print(f"Initial address of x: {id(x)}")
..     x += 1
..     print(f"  Final address of x: {id(x)}")
...
>>> main()
Initial address of n: 140562586057840
Initial address of x: 140562586057840
  Final address of x: 140562586057968
  Final address of n: 140562586057840
0

Như bạn có thể thấy, để trả về nhiều giá trị, bạn chỉ cần sử dụng từ khóa

>>> def main():
..     n = 9001
..     print(f"Initial address of n: {id(n)}")
..     increment(n)
..     print(f"  Final address of n: {id(n)}")
...
>>> def increment(x):
..     print(f"Initial address of x: {id(x)}")
..     x += 1
..     print(f"  Final address of x: {id(x)}")
...
>>> main()
Initial address of n: 140562586057840
Initial address of x: 140562586057840
  Final address of x: 140562586057968
  Final address of n: 140562586057840
66 theo sau là các giá trị hoặc biến được phân tách bằng dấu phẩy

Được trang bị kỹ thuật này, bạn có thể thay đổi câu lệnh

>>> def main():
..     n = 9001
..     print(f"Initial address of n: {id(n)}")
..     increment(n)
..     print(f"  Final address of n: {id(n)}")
...
>>> def increment(x):
..     print(f"Initial address of x: {id(x)}")
..     x += 1
..     print(f"  Final address of x: {id(x)}")
...
>>> main()
Initial address of n: 140562586057840
Initial address of x: 140562586057840
  Final address of x: 140562586057968
  Final address of n: 140562586057840
66 trong
>>> def main():
..     n = 9001
..     print(f"Initial address of n: {id(n)}")
..     increment(n)
..     print(f"  Final address of n: {id(n)}")
...
>>> def increment(x):
..     print(f"Initial address of x: {id(x)}")
..     x += 1
..     print(f"  Final address of x: {id(x)}")
...
>>> main()
Initial address of n: 140562586057840
Initial address of x: 140562586057840
  Final address of x: 140562586057968
  Final address of n: 140562586057840
63 từ mã Python trước đó của bạn để trả về cả lời chào và bộ đếm

>>>

>>> def main():
..     n = 9001
..     print(f"Initial address of n: {id(n)}")
..     increment(n)
..     print(f"  Final address of n: {id(n)}")
...
>>> def increment(x):
..     print(f"Initial address of x: {id(x)}")
..     x += 1
..     print(f"  Final address of x: {id(x)}")
...
>>> main()
Initial address of n: 140562586057840
Initial address of x: 140562586057840
  Final address of x: 140562586057968
  Final address of n: 140562586057840
4

Điều đó vẫn không đúng. Mặc dù hiện tại

>>> def main():
..     n = 9001
..     print(f"Initial address of n: {id(n)}")
..     increment(n)
..     print(f"  Final address of n: {id(n)}")
...
>>> def increment(x):
..     print(f"Initial address of x: {id(x)}")
..     x += 1
..     print(f"  Final address of x: {id(x)}")
...
>>> main()
Initial address of n: 140562586057840
Initial address of x: 140562586057840
  Final address of x: 140562586057968
  Final address of n: 140562586057840
63 trả về nhiều giá trị nhưng chúng đang được in dưới dạng
>>> def main():
..     n = 9001
..     print(f"Initial address of n: {id(n)}")
..     increment(n)
..     print(f"  Final address of n: {id(n)}")
...
>>> def increment(x):
..     print(f"Initial address of x: {id(x)}")
..     x += 1
..     print(f"  Final address of x: {id(x)}")
...
>>> main()
Initial address of n: 140562586057840
Initial address of x: 140562586057840
  Final address of x: 140562586057968
  Final address of n: 140562586057840
00, đây không phải là ý định của bạn. Hơn nữa, biến
>>> def main():
..     n = 9001
..     print(f"Initial address of n: {id(n)}")
..     increment(n)
..     print(f"  Final address of n: {id(n)}")
...
>>> def increment(x):
..     print(f"Initial address of x: {id(x)}")
..     x += 1
..     print(f"  Final address of x: {id(x)}")
...
>>> main()
Initial address of n: 140562586057840
Initial address of x: 140562586057840
  Final address of x: 140562586057968
  Final address of n: 140562586057840
64 ban đầu vẫn ở
>>> def main():
..     n = 9001
..     print(f"Initial address of n: {id(n)}")
..     increment(n)
..     print(f"  Final address of n: {id(n)}")
...
>>> def increment(x):
..     print(f"Initial address of x: {id(x)}")
..     x += 1
..     print(f"  Final address of x: {id(x)}")
...
>>> main()
Initial address of n: 140562586057840
Initial address of x: 140562586057840
  Final address of x: 140562586057968
  Final address of n: 140562586057840
02

Để làm sạch đầu ra của bạn và nhận được kết quả mong muốn, bạn sẽ phải gán lại biến

>>> def main():
..     n = 9001
..     print(f"Initial address of n: {id(n)}")
..     increment(n)
..     print(f"  Final address of n: {id(n)}")
...
>>> def increment(x):
..     print(f"Initial address of x: {id(x)}")
..     x += 1
..     print(f"  Final address of x: {id(x)}")
...
>>> main()
Initial address of n: 140562586057840
Initial address of x: 140562586057840
  Final address of x: 140562586057968
  Final address of n: 140562586057840
64 của mình với mỗi lệnh gọi tới
>>> def main():
..     n = 9001
..     print(f"Initial address of n: {id(n)}")
..     increment(n)
..     print(f"  Final address of n: {id(n)}")
...
>>> def increment(x):
..     print(f"Initial address of x: {id(x)}")
..     x += 1
..     print(f"  Final address of x: {id(x)}")
...
>>> main()
Initial address of n: 140562586057840
Initial address of x: 140562586057840
  Final address of x: 140562586057968
  Final address of n: 140562586057840
63

>>>

>>> def main():
..     n = 9001
..     print(f"Initial address of n: {id(n)}")
..     increment(n)
..     print(f"  Final address of n: {id(n)}")
...
>>> def increment(x):
..     print(f"Initial address of x: {id(x)}")
..     x += 1
..     print(f"  Final address of x: {id(x)}")
...
>>> main()
Initial address of n: 140562586057840
Initial address of x: 140562586057840
  Final address of x: 140562586057968
  Final address of n: 140562586057840
1

Bây giờ, sau khi gán lại từng biến bằng lệnh gọi tới

>>> def main():
..     n = 9001
..     print(f"Initial address of n: {id(n)}")
..     increment(n)
..     print(f"  Final address of n: {id(n)}")
...
>>> def increment(x):
..     print(f"Initial address of x: {id(x)}")
..     x += 1
..     print(f"  Final address of x: {id(x)}")
...
>>> main()
Initial address of n: 140562586057840
Initial address of x: 140562586057840
  Final address of x: 140562586057968
  Final address of n: 140562586057840
63, bạn có thể thấy kết quả mong muốn

Gán giá trị trả về cho biến là cách tốt nhất để đạt được kết quả tương tự như chuyển qua tham chiếu trong Python. Bạn sẽ tìm hiểu lý do tại sao, cùng với một số phương pháp bổ sung, trong phần về các phương pháp hay nhất

Loại bỏ các quảng cáo

Tạo các hàm trả về nhiều lần có điều kiện

Đây là một trường hợp sử dụng cụ thể để trả về nhiều giá trị trong đó hàm có thể được sử dụng trong câu lệnh có điều kiện và có các tác dụng phụ bổ sung như sửa đổi một biến bên ngoài được chuyển vào làm đối số

Hãy xem xét tiêu chuẩn Int32. Hàm TryParse trong C#, trả về một giá trị Boolean và hoạt động trên một tham chiếu đến một đối số nguyên cùng một lúc

>>> def main():
..     n = 9001
..     print(f"Initial address of n: {id(n)}")
..     increment(n)
..     print(f"  Final address of n: {id(n)}")
...
>>> def increment(x):
..     print(f"Initial address of x: {id(x)}")
..     x += 1
..     print(f"  Final address of x: {id(x)}")
...
>>> main()
Initial address of n: 140562586057840
Initial address of x: 140562586057840
  Final address of x: 140562586057968
  Final address of n: 140562586057840
3

Hàm này cố gắng chuyển đổi một số

>>> def main():
..     n = 9001
..     print(f"Initial address of n: {id(n)}")
..     increment(n)
..     print(f"  Final address of n: {id(n)}")
...
>>> def increment(x):
..     print(f"Initial address of x: {id(x)}")
..     x += 1
..     print(f"  Final address of x: {id(x)}")
...
>>> main()
Initial address of n: 140562586057840
Initial address of x: 140562586057840
  Final address of x: 140562586057968
  Final address of n: 140562586057840
06 thành số nguyên có chữ ký 32 bit bằng cách sử dụng từ khóa
>>> def main():
..     n = 9001
..     print(f"Initial address of n: {id(n)}")
..     increment(n)
..     print(f"  Final address of n: {id(n)}")
...
>>> def increment(x):
..     print(f"Initial address of x: {id(x)}")
..     x += 1
..     print(f"  Final address of x: {id(x)}")
...
>>> main()
Initial address of n: 140562586057840
Initial address of x: 140562586057840
  Final address of x: 140562586057968
  Final address of n: 140562586057840
07. Có hai kết quả có thể xảy ra

  1. Nếu phân tích cú pháp thành công, thì tham số đầu ra sẽ được đặt thành số nguyên kết quả và hàm sẽ trả về
    >>> def main():
    ..     n = 9001
    ..     print(f"Initial address of n: {id(n)}")
    ..     increment(n)
    ..     print(f"  Final address of n: {id(n)}")
    ...
    >>> def increment(x):
    ..     print(f"Initial address of x: {id(x)}")
    ..     x += 1
    ..     print(f"  Final address of x: {id(x)}")
    ...
    >>> main()
    Initial address of n: 140562586057840
    Initial address of x: 140562586057840
      Final address of x: 140562586057968
      Final address of n: 140562586057840
    
    08
  2. Nếu phân tích cú pháp không thành công, thì tham số đầu ra sẽ được đặt thành
    >>> def main():
    ..     n = 9001
    ..     print(f"Initial address of n: {id(n)}")
    ..     increment(n)
    ..     print(f"  Final address of n: {id(n)}")
    ...
    >>> def increment(x):
    ..     print(f"Initial address of x: {id(x)}")
    ..     x += 1
    ..     print(f"  Final address of x: {id(x)}")
    ...
    >>> main()
    Initial address of n: 140562586057840
    Initial address of x: 140562586057840
      Final address of x: 140562586057968
      Final address of n: 140562586057840
    
    02 và hàm sẽ trả về
    >>> def main():
    ..     n = 9001
    ..     print(f"Initial address of n: {id(n)}")
    ..     increment(n)
    ..     print(f"  Final address of n: {id(n)}")
    ...
    >>> def increment(x):
    ..     print(f"Initial address of x: {id(x)}")
    ..     x += 1
    ..     print(f"  Final address of x: {id(x)}")
    ...
    >>> main()
    Initial address of n: 140562586057840
    Initial address of x: 140562586057840
      Final address of x: 140562586057968
      Final address of n: 140562586057840
    
    40

Bạn có thể thấy điều này trong thực tế trong ví dụ sau, ví dụ này cố gắng chuyển đổi một số chuỗi khác nhau

>>> def main():
..     arg = 4
..     square(arg)
..     print(arg)
...
>>> def square(n):
..     n *= n
...
>>> main()
4
0

Đoạn mã trên, cố gắng chuyển đổi các chuỗi có định dạng khác nhau thành số nguyên thông qua

>>> def main():
..     n = 9001
..     print(f"Initial address of n: {id(n)}")
..     increment(n)
..     print(f"  Final address of n: {id(n)}")
...
>>> def increment(x):
..     print(f"Initial address of x: {id(x)}")
..     x += 1
..     print(f"  Final address of x: {id(x)}")
...
>>> main()
Initial address of n: 140562586057840
Initial address of x: 140562586057840
  Final address of x: 140562586057968
  Final address of n: 140562586057840
41, xuất ra kết quả như sau

>>> def main():
..     arg = 4
..     square(arg)
..     print(arg)
...
>>> def square(n):
..     n *= n
...
>>> main()
4
1

Để triển khai một chức năng tương tự trong Python, bạn có thể sử dụng nhiều giá trị trả về như bạn đã thấy trước đó

>>> def main():
..     arg = 4
..     square(arg)
..     print(arg)
...
>>> def square(n):
..     n *= n
...
>>> main()
4
2

>>> def main():
..     n = 9001
..     print(f"Initial address of n: {id(n)}")
..     increment(n)
..     print(f"  Final address of n: {id(n)}")
...
>>> def increment(x):
..     print(f"Initial address of x: {id(x)}")
..     x += 1
..     print(f"  Final address of x: {id(x)}")
...
>>> main()
Initial address of n: 140562586057840
Initial address of x: 140562586057840
  Final address of x: 140562586057968
  Final address of n: 140562586057840
42 này trả về hai giá trị. Giá trị đầu tiên cho biết chuyển đổi có thành công hay không và giá trị thứ hai giữ kết quả (hoặc
>>> def main():
..     n = 9001
..     print(f"Initial address of n: {id(n)}")
..     increment(n)
..     print(f"  Final address of n: {id(n)}")
...
>>> def increment(x):
..     print(f"Initial address of x: {id(x)}")
..     x += 1
..     print(f"  Final address of x: {id(x)}")
...
>>> main()
Initial address of n: 140562586057840
Initial address of x: 140562586057840
  Final address of x: 140562586057968
  Final address of n: 140562586057840
43, trong trường hợp không thành công)

Tuy nhiên, sử dụng chức năng này hơi rắc rối vì bạn cần giải nén các giá trị trả về sau mỗi lệnh gọi. Điều này có nghĩa là bạn không thể sử dụng hàm trong câu lệnh

>>> def main():
..     n = 9001
..     print(f"Initial address of n: {id(n)}")
..     increment(n)
..     print(f"  Final address of n: {id(n)}")
...
>>> def increment(x):
..     print(f"Initial address of x: {id(x)}")
..     x += 1
..     print(f"  Final address of x: {id(x)}")
...
>>> main()
Initial address of n: 140562586057840
Initial address of x: 140562586057840
  Final address of x: 140562586057968
  Final address of n: 140562586057840
44

>>>

>>> def main():
..     arg = 4
..     square(arg)
..     print(arg)
...
>>> def square(n):
..     n *= n
...
>>> main()
4
3

Mặc dù nó thường hoạt động bằng cách trả về nhiều giá trị, nhưng không thể sử dụng

>>> def main():
..     n = 9001
..     print(f"Initial address of n: {id(n)}")
..     increment(n)
..     print(f"  Final address of n: {id(n)}")
...
>>> def increment(x):
..     print(f"Initial address of x: {id(x)}")
..     x += 1
..     print(f"  Final address of x: {id(x)}")
...
>>> main()
Initial address of n: 140562586057840
Initial address of x: 140562586057840
  Final address of x: 140562586057968
  Final address of n: 140562586057840
42 để kiểm tra điều kiện. Điều đó có nghĩa là bạn còn nhiều việc phải làm

Bạn có thể tận dụng tính linh hoạt của Python và đơn giản hóa hàm để trả về một giá trị duy nhất thuộc các loại khác nhau tùy thuộc vào việc chuyển đổi có thành công hay không

>>> def main():
..     arg = 4
..     square(arg)
..     print(arg)
...
>>> def square(n):
..     n *= n
...
>>> main()
4
4

Với khả năng các hàm Python trả về các loại dữ liệu khác nhau, giờ đây bạn có thể sử dụng hàm này trong một câu lệnh có điều kiện. Nhưng bằng cách nào?

Bằng cách tận dụng tính linh hoạt của Python trong các loại đối tượng, cũng như các biểu thức gán mới trong Python 3. 8, bạn có thể gọi hàm đơn giản hóa này trong câu lệnh

>>> def main():
..     n = 9001
..     print(f"Initial address of n: {id(n)}")
..     increment(n)
..     print(f"  Final address of n: {id(n)}")
...
>>> def increment(x):
..     print(f"Initial address of x: {id(x)}")
..     x += 1
..     print(f"  Final address of x: {id(x)}")
...
>>> main()
Initial address of n: 140562586057840
Initial address of x: 140562586057840
  Final address of x: 140562586057968
  Final address of n: 140562586057840
44 có điều kiện và nhận giá trị trả về nếu kiểm tra vượt qua

>>>

>>> def main():
..     arg = 4
..     square(arg)
..     print(arg)
...
>>> def square(n):
..     n *= n
...
>>> main()
4
5

Ồ. Phiên bản Python của

>>> def main():
..     n = 9001
..     print(f"Initial address of n: {id(n)}")
..     increment(n)
..     print(f"  Final address of n: {id(n)}")
...
>>> def increment(x):
..     print(f"Initial address of x: {id(x)}")
..     x += 1
..     print(f"  Final address of x: {id(x)}")
...
>>> main()
Initial address of n: 140562586057840
Initial address of x: 140562586057840
  Final address of x: 140562586057968
  Final address of n: 140562586057840
42 này thậm chí còn mạnh hơn phiên bản C#, cho phép bạn sử dụng nó trong các câu điều kiện và trong các biểu thức số học

Với một chút khéo léo, bạn đã sao chép một mẫu chuyển qua tham chiếu cụ thể và hữu ích mà không thực sự chuyển đối số theo tham chiếu. Trên thực tế, bạn lại đang gán các giá trị trả về khi sử dụng toán tử biểu thức gán (

>>> def main():
..     n = 9001
..     print(f"Initial address of n: {id(n)}")
..     increment(n)
..     print(f"  Final address of n: {id(n)}")
...
>>> def increment(x):
..     print(f"Initial address of x: {id(x)}")
..     x += 1
..     print(f"  Final address of x: {id(x)}")
...
>>> main()
Initial address of n: 140562586057840
Initial address of x: 140562586057840
  Final address of x: 140562586057968
  Final address of n: 140562586057840
48) và sử dụng giá trị trả về trực tiếp trong các biểu thức Python

Cho đến giờ, bạn đã biết truyền tham chiếu nghĩa là gì, nó khác với truyền giá trị như thế nào và cách tiếp cận của Python khác với cả hai. Bây giờ bạn đã sẵn sàng xem xét kỹ hơn cách Python xử lý các đối số hàm

Loại bỏ các quảng cáo

Truyền đối số trong Python

Python chuyển đối số bằng cách gán. Nghĩa là, khi bạn gọi một hàm Python, mỗi đối số của hàm sẽ trở thành một biến mà giá trị được truyền vào được gán

Do đó, bạn có thể tìm hiểu các chi tiết quan trọng về cách Python xử lý các đối số của hàm bằng cách hiểu cách thức hoạt động của cơ chế gán, ngay cả các hàm bên ngoài

Hiểu bài tập trong Python

Tham chiếu ngôn ngữ của Python cho các câu lệnh gán cung cấp các chi tiết sau

  • Nếu mục tiêu gán là một mã định danh hoặc tên biến, thì tên này được liên kết với đối tượng. Ví dụ, trong
    >>> def main():
    ..     n = 9001
    ..     print(f"Initial address of n: {id(n)}")
    ..     increment(n)
    ..     print(f"  Final address of n: {id(n)}")
    ...
    >>> def increment(x):
    ..     print(f"Initial address of x: {id(x)}")
    ..     x += 1
    ..     print(f"  Final address of x: {id(x)}")
    ...
    >>> main()
    Initial address of n: 140562586057840
    Initial address of x: 140562586057840
      Final address of x: 140562586057968
      Final address of n: 140562586057840
    
    49,
    using System;
    
    // Source:
    // https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/passing-parameters
    class Program
    {
        static void Main(string[] args)
        {
            int arg;
    
            // Passing by reference.
            // The value of arg in Main is changed.
            arg = 4;
            squareRef(ref arg);
            Console.WriteLine(arg);
            // Output: 16
        }
    
        static void squareRef(ref int refParameter)
        {
            refParameter *= refParameter;
        }
    }
    
    14 là tên và
    >>> def main():
    ..     n = 9001
    ..     print(f"Initial address of n: {id(n)}")
    ..     increment(n)
    ..     print(f"  Final address of n: {id(n)}")
    ...
    >>> def increment(x):
    ..     print(f"Initial address of x: {id(x)}")
    ..     x += 1
    ..     print(f"  Final address of x: {id(x)}")
    ...
    >>> main()
    Initial address of n: 140562586057840
    Initial address of x: 140562586057840
      Final address of x: 140562586057968
      Final address of n: 140562586057840
    
    11 là đối tượng
  • Nếu tên đã được liên kết với một đối tượng riêng biệt, thì tên đó sẽ được liên kết lại với đối tượng mới. Ví dụ: nếu
    using System;
    
    // Source:
    // https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/passing-parameters
    class Program
    {
        static void Main(string[] args)
        {
            int arg;
    
            // Passing by reference.
            // The value of arg in Main is changed.
            arg = 4;
            squareRef(ref arg);
            Console.WriteLine(arg);
            // Output: 16
        }
    
        static void squareRef(ref int refParameter)
        {
            refParameter *= refParameter;
        }
    }
    
    14 đã là
    >>> def main():
    ..     n = 9001
    ..     print(f"Initial address of n: {id(n)}")
    ..     increment(n)
    ..     print(f"  Final address of n: {id(n)}")
    ...
    >>> def increment(x):
    ..     print(f"Initial address of x: {id(x)}")
    ..     x += 1
    ..     print(f"  Final address of x: {id(x)}")
    ...
    >>> main()
    Initial address of n: 140562586057840
    Initial address of x: 140562586057840
      Final address of x: 140562586057968
      Final address of n: 140562586057840
    
    11 và bạn phát hành
    >>> def main():
    ..     n = 9001
    ..     print(f"Initial address of n: {id(n)}")
    ..     increment(n)
    ..     print(f"  Final address of n: {id(n)}")
    ...
    >>> def increment(x):
    ..     print(f"Initial address of x: {id(x)}")
    ..     x += 1
    ..     print(f"  Final address of x: {id(x)}")
    ...
    >>> main()
    Initial address of n: 140562586057840
    Initial address of x: 140562586057840
      Final address of x: 140562586057968
      Final address of n: 140562586057840
    
    14, thì tên biến
    using System;
    
    // Source:
    // https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/passing-parameters
    class Program
    {
        static void Main(string[] args)
        {
            int arg;
    
            // Passing by reference.
            // The value of arg in Main is changed.
            arg = 4;
            squareRef(ref arg);
            Console.WriteLine(arg);
            // Output: 16
        }
    
        static void squareRef(ref int refParameter)
        {
            refParameter *= refParameter;
        }
    }
    
    14 được ràng buộc lại thành
    >>> def main():
    ..     n = 9001
    ..     print(f"Initial address of n: {id(n)}")
    ..     increment(n)
    ..     print(f"  Final address of n: {id(n)}")
    ...
    >>> def increment(x):
    ..     print(f"Initial address of x: {id(x)}")
    ..     x += 1
    ..     print(f"  Final address of x: {id(x)}")
    ...
    >>> main()
    Initial address of n: 140562586057840
    Initial address of x: 140562586057840
      Final address of x: 140562586057968
      Final address of n: 140562586057840
    
    16

Tất cả các đối tượng Python được triển khai trong một cấu trúc cụ thể. Một trong những thuộc tính của cấu trúc này là bộ đếm theo dõi xem có bao nhiêu tên đã được liên kết với đối tượng này

Ghi chú. Bộ đếm này được gọi là bộ đếm tham chiếu vì nó theo dõi xem có bao nhiêu tham chiếu hoặc tên trỏ đến cùng một đối tượng. Đừng nhầm lẫn bộ đếm tham chiếu với khái niệm chuyển qua tham chiếu, vì hai khái niệm này không liên quan

Tài liệu Python cung cấp thêm chi tiết về số lượng tham chiếu

Hãy làm theo ví dụ về

>>> def main():
..     n = 9001
..     print(f"Initial address of n: {id(n)}")
..     increment(n)
..     print(f"  Final address of n: {id(n)}")
...
>>> def increment(x):
..     print(f"Initial address of x: {id(x)}")
..     x += 1
..     print(f"  Final address of x: {id(x)}")
...
>>> main()
Initial address of n: 140562586057840
Initial address of x: 140562586057840
  Final address of x: 140562586057968
  Final address of n: 140562586057840
49 và kiểm tra xem điều gì sẽ xảy ra khi bạn gán một giá trị cho một biến mới

  1. Nếu một đối tượng đại diện cho giá trị
    >>> def main():
    ..     n = 9001
    ..     print(f"Initial address of n: {id(n)}")
    ..     increment(n)
    ..     print(f"  Final address of n: {id(n)}")
    ...
    >>> def increment(x):
    ..     print(f"Initial address of x: {id(x)}")
    ..     x += 1
    ..     print(f"  Final address of x: {id(x)}")
    ...
    >>> main()
    Initial address of n: 140562586057840
    Initial address of x: 140562586057840
      Final address of x: 140562586057968
      Final address of n: 140562586057840
    
    11 đã tồn tại, thì nó sẽ được truy xuất. Mặt khác, nó được tạo ra
  2. Bộ đếm tham chiếu của đối tượng này được tăng lên
  3. Một mục nhập được thêm vào không gian tên hiện tại để liên kết mã định danh
    using System;
    
    // Source:
    // https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/passing-parameters
    class Program
    {
        static void Main(string[] args)
        {
            int arg;
    
            // Passing by reference.
            // The value of arg in Main is changed.
            arg = 4;
            squareRef(ref arg);
            Console.WriteLine(arg);
            // Output: 16
        }
    
        static void squareRef(ref int refParameter)
        {
            refParameter *= refParameter;
        }
    }
    
    14 với đối tượng đại diện cho
    >>> def main():
    ..     n = 9001
    ..     print(f"Initial address of n: {id(n)}")
    ..     increment(n)
    ..     print(f"  Final address of n: {id(n)}")
    ...
    >>> def increment(x):
    ..     print(f"Initial address of x: {id(x)}")
    ..     x += 1
    ..     print(f"  Final address of x: {id(x)}")
    ...
    >>> main()
    Initial address of n: 140562586057840
    Initial address of x: 140562586057840
      Final address of x: 140562586057968
      Final address of n: 140562586057840
    
    11. Mục nhập này trên thực tế là một cặp khóa-giá trị được lưu trữ trong từ điển. Một đại diện của từ điển đó được trả về bởi
    >>> def main():
    ..     n = 9001
    ..     print(f"Initial address of n: {id(n)}")
    ..     increment(n)
    ..     print(f"  Final address of n: {id(n)}")
    ...
    >>> def increment(x):
    ..     print(f"Initial address of x: {id(x)}")
    ..     x += 1
    ..     print(f"  Final address of x: {id(x)}")
    ...
    >>> main()
    Initial address of n: 140562586057840
    Initial address of x: 140562586057840
      Final address of x: 140562586057968
      Final address of n: 140562586057840
    
    31 hoặc
    >>> def main():
    ..     n = 9001
    ..     print(f"Initial address of n: {id(n)}")
    ..     increment(n)
    ..     print(f"  Final address of n: {id(n)}")
    ...
    >>> def increment(x):
    ..     print(f"Initial address of x: {id(x)}")
    ..     x += 1
    ..     print(f"  Final address of x: {id(x)}")
    ...
    >>> main()
    Initial address of n: 140562586057840
    Initial address of x: 140562586057840
      Final address of x: 140562586057968
      Final address of n: 140562586057840
    
    32

Bây giờ, đây là điều sẽ xảy ra nếu bạn gán lại

using System;

// Source:
// https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/passing-parameters
class Program
{
    static void Main(string[] args)
    {
        int arg;

        // Passing by reference.
        // The value of arg in Main is changed.
        arg = 4;
        squareRef(ref arg);
        Console.WriteLine(arg);
        // Output: 16
    }

    static void squareRef(ref int refParameter)
    {
        refParameter *= refParameter;
    }
}
14 cho một giá trị khác

  1. Bộ đếm tham chiếu của đối tượng đại diện cho
    >>> def main():
    ..     n = 9001
    ..     print(f"Initial address of n: {id(n)}")
    ..     increment(n)
    ..     print(f"  Final address of n: {id(n)}")
    ...
    >>> def increment(x):
    ..     print(f"Initial address of x: {id(x)}")
    ..     x += 1
    ..     print(f"  Final address of x: {id(x)}")
    ...
    >>> main()
    Initial address of n: 140562586057840
    Initial address of x: 140562586057840
      Final address of x: 140562586057968
      Final address of n: 140562586057840
    
    11 bị giảm
  2. Bộ đếm tham chiếu của đối tượng đại diện cho giá trị mới được tăng lên
  3. Từ điển cho không gian tên hiện tại được cập nhật để liên kết
    using System;
    
    // Source:
    // https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/passing-parameters
    class Program
    {
        static void Main(string[] args)
        {
            int arg;
    
            // Passing by reference.
            // The value of arg in Main is changed.
            arg = 4;
            squareRef(ref arg);
            Console.WriteLine(arg);
            // Output: 16
        }
    
        static void squareRef(ref int refParameter)
        {
            refParameter *= refParameter;
        }
    }
    
    14 với đối tượng đại diện cho giá trị mới

Python cho phép bạn lấy số lượng tham chiếu cho các giá trị tùy ý bằng hàm

>>> def main():
..     n = 9001
..     print(f"Initial address of n: {id(n)}")
..     increment(n)
..     print(f"  Final address of n: {id(n)}")
...
>>> def increment(x):
..     print(f"Initial address of x: {id(x)}")
..     x += 1
..     print(f"  Final address of x: {id(x)}")
...
>>> main()
Initial address of n: 140562586057840
Initial address of x: 140562586057840
  Final address of x: 140562586057968
  Final address of n: 140562586057840
36. Bạn có thể sử dụng nó để minh họa cách gán tăng và giảm các bộ đếm tham chiếu này. Lưu ý rằng trình thông dịch tương tác sử dụng hành vi sẽ mang lại các kết quả khác nhau, vì vậy bạn nên chạy đoạn mã sau từ một tệp

>>> def main():
..     arg = 4
..     square(arg)
..     print(arg)
...
>>> def square(n):
..     n *= n
...
>>> main()
4
6

Tập lệnh này sẽ hiển thị số lượng tham chiếu cho từng giá trị trước khi gán, sau khi gán và sau khi gán lại

>>> def main():
..     arg = 4
..     square(arg)
..     print(arg)
...
>>> def square(n):
..     n *= n
...
>>> main()
4
7

Các kết quả này minh họa mối quan hệ giữa các mã định danh (tên biến) và các đối tượng Python đại diện cho các giá trị riêng biệt. Khi bạn gán nhiều biến cho cùng một giá trị, Python sẽ tăng bộ đếm tham chiếu cho đối tượng hiện có và cập nhật không gian tên hiện tại thay vì tạo các đối tượng trùng lặp trong bộ nhớ

Trong phần tiếp theo, bạn sẽ xây dựng dựa trên hiểu biết hiện tại của mình về các hoạt động gán bằng cách khám phá cách Python xử lý các đối số hàm

Khám phá các đối số chức năng

Đối số hàm trong Python là biến cục bộ. Điều đó nghĩa là gì? . Các phạm vi này được đại diện bởi các từ điển không gian tên được đề cập trong phần trước. Bạn có thể sử dụng

>>> def main():
..     n = 9001
..     print(f"Initial address of n: {id(n)}")
..     increment(n)
..     print(f"  Final address of n: {id(n)}")
...
>>> def increment(x):
..     print(f"Initial address of x: {id(x)}")
..     x += 1
..     print(f"  Final address of x: {id(x)}")
...
>>> main()
Initial address of n: 140562586057840
Initial address of x: 140562586057840
  Final address of x: 140562586057968
  Final address of n: 140562586057840
31 và
>>> def main():
..     n = 9001
..     print(f"Initial address of n: {id(n)}")
..     increment(n)
..     print(f"  Final address of n: {id(n)}")
...
>>> def increment(x):
..     print(f"Initial address of x: {id(x)}")
..     x += 1
..     print(f"  Final address of x: {id(x)}")
...
>>> main()
Initial address of n: 140562586057840
Initial address of x: 140562586057840
  Final address of x: 140562586057968
  Final address of n: 140562586057840
32 để truy xuất từ ​​điển không gian tên cục bộ và toàn cầu, tương ứng

Khi thực hiện, mỗi hàm có không gian tên cục bộ riêng

>>>

>>> def main():
..     arg = 4
..     square(arg)
..     print(arg)
...
>>> def square(n):
..     n *= n
...
>>> main()
4
8

Sử dụng

>>> def main():
..     n = 9001
..     print(f"Initial address of n: {id(n)}")
..     increment(n)
..     print(f"  Final address of n: {id(n)}")
...
>>> def increment(x):
..     print(f"Initial address of x: {id(x)}")
..     x += 1
..     print(f"  Final address of x: {id(x)}")
...
>>> main()
Initial address of n: 140562586057840
Initial address of x: 140562586057840
  Final address of x: 140562586057968
  Final address of n: 140562586057840
31, bạn có thể chứng minh rằng các đối số của hàm trở thành các biến thông thường trong không gian tên cục bộ của hàm. Hãy thêm một đối số,
>>> def main():
..     arg = 4
..     square(arg)
..     print(arg)
...
>>> def square(n):
..     n *= n
...
>>> main()
4
00, vào hàm

>>>

>>> def main():
..     arg = 4
..     square(arg)
..     print(arg)
...
>>> def square(n):
..     n *= n
...
>>> main()
4
9

Bạn cũng có thể sử dụng

>>> def main():
..     n = 9001
..     print(f"Initial address of n: {id(n)}")
..     increment(n)
..     print(f"  Final address of n: {id(n)}")
...
>>> def increment(x):
..     print(f"Initial address of x: {id(x)}")
..     x += 1
..     print(f"  Final address of x: {id(x)}")
...
>>> main()
Initial address of n: 140562586057840
Initial address of x: 140562586057840
  Final address of x: 140562586057968
  Final address of n: 140562586057840
36 để chỉ ra cách các đối số của hàm tăng bộ đếm tham chiếu cho một đối tượng

>>>

using System;

// Source:
// https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/passing-parameters
class Program
{
    static void Main(string[] args)
    {
        int arg;

        // Passing by value.
        // The value of arg in Main is not changed.
        arg = 4;
        squareVal(arg);
        Console.WriteLine(arg);
        // Output: 4
    }

    static void squareVal(int valParameter)
    {
        valParameter *= valParameter;
    }
}
0

Tập lệnh trên xuất ra số lượng tham chiếu cho

>>> def main():
..     arg = 4
..     square(arg)
..     print(arg)
...
>>> def square(n):
..     n *= n
...
>>> main()
4
02 đầu tiên bên ngoài, sau đó bên trong
>>> def main():
..     arg = 4
..     square(arg)
..     print(arg)
...
>>> def square(n):
..     n *= n
...
>>> main()
4
03, hiển thị số lượng tham chiếu tăng không phải một mà là hai

Đó là bởi vì, ngoài bản thân

>>> def main():
..     arg = 4
..     square(arg)
..     print(arg)
...
>>> def square(n):
..     n *= n
...
>>> main()
4
03, lệnh gọi tới
>>> def main():
..     n = 9001
..     print(f"Initial address of n: {id(n)}")
..     increment(n)
..     print(f"  Final address of n: {id(n)}")
...
>>> def increment(x):
..     print(f"Initial address of x: {id(x)}")
..     x += 1
..     print(f"  Final address of x: {id(x)}")
...
>>> main()
Initial address of n: 140562586057840
Initial address of x: 140562586057840
  Final address of x: 140562586057968
  Final address of n: 140562586057840
36 bên trong
>>> def main():
..     arg = 4
..     square(arg)
..     print(arg)
...
>>> def square(n):
..     n *= n
...
>>> main()
4
03 cũng nhận được
>>> def main():
..     arg = 4
..     square(arg)
..     print(arg)
...
>>> def square(n):
..     n *= n
...
>>> main()
4
00 làm đối số. Điều này đặt
>>> def main():
..     arg = 4
..     square(arg)
..     print(arg)
...
>>> def square(n):
..     n *= n
...
>>> main()
4
00 trong không gian tên cục bộ cho
>>> def main():
..     n = 9001
..     print(f"Initial address of n: {id(n)}")
..     increment(n)
..     print(f"  Final address of n: {id(n)}")
...
>>> def increment(x):
..     print(f"Initial address of x: {id(x)}")
..     x += 1
..     print(f"  Final address of x: {id(x)}")
...
>>> main()
Initial address of n: 140562586057840
Initial address of x: 140562586057840
  Final address of x: 140562586057968
  Final address of n: 140562586057840
36, thêm một tham chiếu bổ sung cho
>>> def main():
..     arg = 4
..     square(arg)
..     print(arg)
...
>>> def square(n):
..     n *= n
...
>>> main()
4
02

Bằng cách kiểm tra các không gian tên và số lượng tham chiếu bên trong các hàm, bạn có thể thấy rằng các đối số của hàm hoạt động chính xác như các phép gán. Python tạo các liên kết trong không gian tên cục bộ của hàm giữa các mã định danh và các đối tượng Python đại diện cho các giá trị đối số. Mỗi ràng buộc này tăng bộ đếm tham chiếu của đối tượng

Bây giờ bạn có thể thấy cách Python truyền đối số bằng phép gán

Loại bỏ các quảng cáo

Sao chép thông qua tham chiếu với Python

Sau khi kiểm tra các không gian tên trong phần trước, bạn có thể hỏi tại sao

>>> def main():
..     arg = 4
..     square(arg)
..     print(arg)
...
>>> def square(n):
..     n *= n
...
>>> main()
4
11 không được đề cập như một cách để sửa đổi các biến như thể chúng được chuyển qua tham chiếu

>>>

using System;

// Source:
// https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/passing-parameters
class Program
{
    static void Main(string[] args)
    {
        int arg;

        // Passing by value.
        // The value of arg in Main is not changed.
        arg = 4;
        squareVal(arg);
        Console.WriteLine(arg);
        // Output: 4
    }

    static void squareVal(int valParameter)
    {
        valParameter *= valParameter;
    }
}
1

Việc sử dụng câu lệnh

>>> def main():
..     arg = 4
..     square(arg)
..     print(arg)
...
>>> def square(n):
..     n *= n
...
>>> main()
4
11 thường làm mất đi tính rõ ràng của mã của bạn. Nó có thể tạo ra một số vấn đề, bao gồm những vấn đề sau

  • Các biến miễn phí, dường như không liên quan đến bất cứ điều gì
  • Các hàm không có đối số rõ ràng cho các biến đã nói
  • Các hàm không thể được sử dụng chung với các biến hoặc đối số khác vì chúng dựa trên một biến toàn cục duy nhất
  • Thiếu an toàn luồng khi sử dụng các biến toàn cục

Đối chiếu ví dụ trước với ví dụ sau, ví dụ này trả về một giá trị rõ ràng

>>>

using System;

// Source:
// https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/passing-parameters
class Program
{
    static void Main(string[] args)
    {
        int arg;

        // Passing by value.
        // The value of arg in Main is not changed.
        arg = 4;
        squareVal(arg);
        Console.WriteLine(arg);
        // Output: 4
    }

    static void squareVal(int valParameter)
    {
        valParameter *= valParameter;
    }
}
2

Tốt hơn nhiều. Bạn tránh được tất cả các vấn đề tiềm ẩn với các biến toàn cục và bằng cách yêu cầu một đối số, bạn làm cho chức năng của mình rõ ràng hơn

Mặc dù không phải là ngôn ngữ chuyển qua tham chiếu hay ngôn ngữ chuyển qua giá trị, nhưng Python không có thiếu sót nào về mặt đó. Tính linh hoạt của nó nhiều hơn đáp ứng thách thức

Thực hành tốt nhất. Trả lại và chỉ định lại

Bạn đã chạm vào việc trả về các giá trị từ hàm và gán lại chúng cho một biến. Đối với các hàm hoạt động trên một giá trị, việc trả về giá trị rõ ràng hơn nhiều so với sử dụng tham chiếu. Hơn nữa, vì Python đã sử dụng con trỏ phía sau nên sẽ không có thêm lợi ích về hiệu suất ngay cả khi nó có thể truyền đối số bằng cách tham chiếu

Nhằm mục đích viết các hàm đơn mục đích trả về một giá trị, sau đó (tái) gán giá trị đó cho các biến, như trong ví dụ sau

using System;

// Source:
// https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/passing-parameters
class Program
{
    static void Main(string[] args)
    {
        int arg;

        // Passing by value.
        // The value of arg in Main is not changed.
        arg = 4;
        squareVal(arg);
        Console.WriteLine(arg);
        // Output: 4
    }

    static void squareVal(int valParameter)
    {
        valParameter *= valParameter;
    }
}
3

Việc trả về và gán giá trị cũng làm cho ý định của bạn trở nên rõ ràng và mã của bạn dễ hiểu và dễ kiểm tra hơn

Đối với các hàm hoạt động trên nhiều giá trị, bạn đã thấy rằng Python có khả năng trả về một bộ giá trị. Bạn thậm chí còn vượt qua sự sang trọng của Int32. TryParse() trong C# nhờ tính linh hoạt của Python

Nếu bạn cần thao tác trên nhiều giá trị, thì bạn có thể viết các hàm đơn mục đích trả về nhiều giá trị, sau đó (tái) gán các giá trị đó cho các biến. Đây là một ví dụ

using System;

// Source:
// https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/passing-parameters
class Program
{
    static void Main(string[] args)
    {
        int arg;

        // Passing by value.
        // The value of arg in Main is not changed.
        arg = 4;
        squareVal(arg);
        Console.WriteLine(arg);
        // Output: 4
    }

    static void squareVal(int valParameter)
    {
        valParameter *= valParameter;
    }
}
4

Khi gọi một hàm trả về nhiều giá trị, bạn có thể gán nhiều biến cùng lúc

Thực hành tốt nhất. Sử dụng thuộc tính đối tượng

Các thuộc tính đối tượng có vị trí riêng trong chiến lược gán của Python. Tham chiếu ngôn ngữ của Python cho các câu lệnh gán nêu rõ rằng nếu mục tiêu là một thuộc tính của đối tượng hỗ trợ phép gán, thì đối tượng sẽ được yêu cầu thực hiện phép gán trên thuộc tính đó. Nếu bạn chuyển đối tượng làm đối số cho một hàm, thì các thuộc tính của nó có thể được sửa đổi tại chỗ

Viết các hàm chấp nhận các đối tượng có thuộc tính, sau đó thao tác trực tiếp trên các thuộc tính đó, như trong ví dụ sau

>>>

using System;

// Source:
// https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/passing-parameters
class Program
{
    static void Main(string[] args)
    {
        int arg;

        // Passing by value.
        // The value of arg in Main is not changed.
        arg = 4;
        squareVal(arg);
        Console.WriteLine(arg);
        // Output: 4
    }

    static void squareVal(int valParameter)
    {
        valParameter *= valParameter;
    }
}
5

Lưu ý rằng

>>> def main():
..     arg = 4
..     square(arg)
..     print(arg)
...
>>> def square(n):
..     n *= n
...
>>> main()
4
13 cần được viết để hoạt động trực tiếp trên một thuộc tính, thuộc tính này sẽ được sửa đổi mà không cần gán lại giá trị trả về

Cần nhắc lại rằng bạn nên đảm bảo thuộc tính hỗ trợ gán. Đây là ví dụ tương tự với

>>> def main():
..     arg = 4
..     square(arg)
..     print(arg)
...
>>> def square(n):
..     n *= n
...
>>> main()
4
14, có thuộc tính chỉ đọc

>>>

using System;

// Source:
// https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/passing-parameters
class Program
{
    static void Main(string[] args)
    {
        int arg;

        // Passing by value.
        // The value of arg in Main is not changed.
        arg = 4;
        squareVal(arg);
        Console.WriteLine(arg);
        // Output: 4
    }

    static void squareVal(int valParameter)
    {
        valParameter *= valParameter;
    }
}
6

Cố gắng sửa đổi các thuộc tính không cho phép sửa đổi dẫn đến một

>>> def main():
..     arg = 4
..     square(arg)
..     print(arg)
...
>>> def square(n):
..     n *= n
...
>>> main()
4
15

Ngoài ra, bạn nên chú ý đến các thuộc tính của lớp. Chúng sẽ không thay đổi và một thuộc tính thể hiện sẽ được tạo và sửa đổi

>>>

using System;

// Source:
// https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/passing-parameters
class Program
{
    static void Main(string[] args)
    {
        int arg;

        // Passing by value.
        // The value of arg in Main is not changed.
        arg = 4;
        squareVal(arg);
        Console.WriteLine(arg);
        // Output: 4
    }

    static void squareVal(int valParameter)
    {
        valParameter *= valParameter;
    }
}
7

Vì các thuộc tính của lớp không thay đổi khi được sửa đổi thông qua một thể hiện của lớp, nên bạn cần nhớ tham chiếu đến thuộc tính thể hiện

Loại bỏ các quảng cáo

Thực hành tốt nhất. Sử dụng từ điển và danh sách

Từ điển trong Python là một loại đối tượng khác với tất cả các loại dựng sẵn khác. Chúng được gọi là các loại ánh xạ. Tài liệu của Python về các loại ánh xạ cung cấp một số thông tin chi tiết về thuật ngữ này

Một đối tượng ánh xạ ánh xạ các giá trị có thể băm tới các đối tượng tùy ý. Ánh xạ là các đối tượng có thể thay đổi. Hiện tại chỉ có một loại ánh xạ tiêu chuẩn, từ điển. (Nguồn)

Hướng dẫn này không đề cập đến cách triển khai loại ánh xạ tùy chỉnh, nhưng bạn có thể sao chép chuyển qua tham chiếu bằng cách sử dụng từ điển khiêm tốn. Đây là một ví dụ sử dụng một hàm hoạt động trực tiếp trên các phần tử từ điển

>>>

using System;

// Source:
// https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/passing-parameters
class Program
{
    static void Main(string[] args)
    {
        int arg;

        // Passing by value.
        // The value of arg in Main is not changed.
        arg = 4;
        squareVal(arg);
        Console.WriteLine(arg);
        // Output: 4
    }

    static void squareVal(int valParameter)
    {
        valParameter *= valParameter;
    }
}
8

Vì bạn đang gán lại một giá trị cho khóa từ điển, thao tác trên các phần tử từ điển vẫn là một hình thức gán. Với từ điển, bạn có thêm tính thực tế khi truy cập giá trị đã sửa đổi thông qua cùng một đối tượng từ điển

Mặc dù danh sách không phải là loại ánh xạ, nhưng bạn có thể sử dụng chúng theo cách tương tự như từ điển vì hai đặc điểm quan trọng. khả năng đăng ký và khả năng biến đổi. Những đặc điểm này đáng được giải thích thêm một chút, nhưng trước tiên chúng ta hãy xem các phương pháp hay nhất để bắt chước chuyển qua tham chiếu bằng danh sách Python

Để sao chép chuyển qua tham chiếu bằng danh sách, hãy viết một hàm hoạt động trực tiếp trên các phần tử danh sách

>>>

using System;

// Source:
// https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/passing-parameters
class Program
{
    static void Main(string[] args)
    {
        int arg;

        // Passing by value.
        // The value of arg in Main is not changed.
        arg = 4;
        squareVal(arg);
        Console.WriteLine(arg);
        // Output: 4
    }

    static void squareVal(int valParameter)
    {
        valParameter *= valParameter;
    }
}
9

Vì bạn đang gán lại một giá trị cho một phần tử trong danh sách, hoạt động trên các phần tử danh sách vẫn là một hình thức gán. Tương tự như từ điển, danh sách cho phép bạn truy cập giá trị đã sửa đổi thông qua cùng một đối tượng danh sách

Bây giờ hãy cùng khám phá khả năng đăng ký. Một đối tượng có thể đăng ký được khi một tập hợp con cấu trúc của nó có thể được truy cập bởi các vị trí chỉ mục

>>>

>>> def main():
..     n = 9001
..     print(f"Initial address of n: {id(n)}")
..     increment(n)
..     print(f"  Final address of n: {id(n)}")
...
>>> def increment(x):
..     print(f"Initial address of x: {id(x)}")
..     x += 1
..     print(f"  Final address of x: {id(x)}")
...
>>> main()
Initial address of n: 140562586057840
Initial address of x: 140562586057840
  Final address of x: 140562586057968
  Final address of n: 140562586057840
0

Danh sách, bộ dữ liệu và chuỗi có thể đăng ký được, nhưng bộ thì không. Cố gắng truy cập một phần tử của một đối tượng không thể đăng ký sẽ làm tăng

>>> def main():
..     arg = 4
..     square(arg)
..     print(arg)
...
>>> def square(n):
..     n *= n
...
>>> main()
4
16

Khả năng biến đổi là một chủ đề rộng hơn đòi hỏi phải khám phá thêm và tham khảo tài liệu. Để giữ cho mọi thứ ngắn gọn, một đối tượng có thể thay đổi nếu cấu trúc của nó có thể được thay đổi tại chỗ thay vì yêu cầu chỉ định lại

>>>

>>> def main():
..     n = 9001
..     print(f"Initial address of n: {id(n)}")
..     increment(n)
..     print(f"  Final address of n: {id(n)}")
...
>>> def increment(x):
..     print(f"Initial address of x: {id(x)}")
..     x += 1
..     print(f"  Final address of x: {id(x)}")
...
>>> main()
Initial address of n: 140562586057840
Initial address of x: 140562586057840
  Final address of x: 140562586057968
  Final address of n: 140562586057840
1

Danh sách và bộ có thể thay đổi, cũng như từ điển và các loại ánh xạ khác. Chuỗi và bộ dữ liệu không thể thay đổi. Cố gắng sửa đổi một phần tử của một đối tượng không thể thay đổi sẽ làm tăng

>>> def main():
..     arg = 4
..     square(arg)
..     print(arg)
...
>>> def square(n):
..     n *= n
...
>>> main()
4
16

Sự kết luận

Python hoạt động khác với các ngôn ngữ hỗ trợ truyền đối số theo tham chiếu hoặc theo giá trị. Các đối số của hàm trở thành các biến cục bộ được gán cho mỗi giá trị được truyền cho hàm. Nhưng điều này không ngăn cản bạn đạt được kết quả giống như bạn mong đợi khi chuyển các đối số bằng cách tham chiếu bằng các ngôn ngữ khác

Trong hướng dẫn này, bạn đã học

  • Cách Python xử lý việc gán giá trị cho biến
  • Cách các đối số hàm được truyền bằng phép gán trong Python
  • Tại sao trả lại giá trị là cách thực hành tốt nhất để sao chép thông qua tham chiếu
  • Cách sử dụng thuộc tính, từ điển và danh sách làm phương pháp hay nhất thay thế

Bạn cũng đã học được một số phương pháp hay nhất bổ sung để sao chép các cấu trúc chuyển qua tham chiếu trong Python. Bạn có thể sử dụng kiến ​​thức này để triển khai các mẫu có truyền thống yêu cầu hỗ trợ để chuyển qua tham chiếu

Để tiếp tục hành trình Python của bạn, tôi khuyến khích bạn tìm hiểu sâu hơn về một số chủ đề liên quan mà bạn đã gặp ở đây, chẳng hạn như tính biến đổi, biểu thức gán cũng như không gian tên Python và phạm vi

Hãy tò mò và hẹn gặp lại bạn lần sau

Đánh dấu là đã hoàn thành

Xem ngay Hướng dẫn này có một khóa học video liên quan do nhóm Real Python tạo. Xem nó cùng với hướng dẫn bằng văn bản để hiểu sâu hơn. Vượt qua tham chiếu trong Python. Các phương pháp hay nhất

🐍 Thủ thuật Python 💌

Nhận một Thủ thuật Python ngắn và hấp dẫn được gửi đến hộp thư đến của bạn vài ngày một lần. Không có thư rác bao giờ. Hủy đăng ký bất cứ lúc nào. Được quản lý bởi nhóm Real Python

Chuyển thể hiện của lớp sang hàm python

Gửi cho tôi thủ thuật Python »

Giới thiệu về Marius Mogyorosi

Chuyển thể hiện của lớp sang hàm python
Chuyển thể hiện của lớp sang hàm python

Marius là một người thích mày mò thích sử dụng Python cho các dự án sáng tạo trong và ngoài lĩnh vực bảo mật phần mềm

» Thông tin thêm về Marius


Mỗi hướng dẫn tại Real Python được tạo bởi một nhóm các nhà phát triển để nó đáp ứng các tiêu chuẩn chất lượng cao của chúng tôi. Các thành viên trong nhóm đã làm việc trong hướng dẫn này là

Chuyển thể hiện của lớp sang hàm python

Aldren

Chuyển thể hiện của lớp sang hàm python

David

Chuyển thể hiện của lớp sang hàm python

Geir Arne

Chuyển thể hiện của lớp sang hàm python

Joanna

Chuyển thể hiện của lớp sang hàm python

Gia-cốp

Bậc thầy Kỹ năng Python trong thế giới thực Với quyền truy cập không giới hạn vào Python thực

Chuyển thể hiện của lớp sang hàm python

Tham gia với chúng tôi và có quyền truy cập vào hàng nghìn hướng dẫn, khóa học video thực hành và cộng đồng các Pythonistas chuyên gia

Nâng cao kỹ năng Python của bạn »

Bậc thầy Kỹ năng Python trong thế giới thực
Với quyền truy cập không giới hạn vào Python thực

Tham gia với chúng tôi và có quyền truy cập vào hàng ngàn hướng dẫn, khóa học video thực hành và cộng đồng Pythonistas chuyên gia

Nâng cao kỹ năng Python của bạn »

Bạn nghĩ sao?

Đánh giá bài viết này

Tweet Chia sẻ Chia sẻ Email

Bài học số 1 hoặc điều yêu thích mà bạn đã học được là gì?

Mẹo bình luận. Những nhận xét hữu ích nhất là những nhận xét được viết với mục đích học hỏi hoặc giúp đỡ các sinh viên khác. Nhận các mẹo để đặt câu hỏi hay và nhận câu trả lời cho các câu hỏi phổ biến trong cổng thông tin hỗ trợ của chúng tôi

Bạn có thể chuyển một lớp vào hàm Python không?

tất nhiên là bạn có thể chuyển lớp hoặc hàm hoặc thậm chí là mô-đun . chắc chắn foo(). pass vào đây nó cho địa chỉ ex.

Bạn có thể chuyển một đối tượng tới một hàm trong Python không?

Tham chiếu ngôn ngữ của Python cho các câu lệnh gán nêu rõ rằng nếu mục tiêu là một thuộc tính của đối tượng hỗ trợ phép gán, thì đối tượng sẽ được yêu cầu thực hiện phép gán trên thuộc tính đó. Nếu bạn chuyển đối tượng làm đối số cho một hàm, thì các thuộc tính của nó có thể được sửa đổi tại chỗ .

Thể hiện của một lớp trong Python là gì?

Thể hiện là đối tượng thuộc về một lớp . Chẳng hạn, danh sách là một lớp trong Python. Khi chúng ta tạo một danh sách, chúng ta có một thể hiện của lớp danh sách.

__ đại diện __ là gì?

Hàm __repr__() của Python trả về biểu diễn đối tượng ở định dạng chuỗi . Phương thức này được gọi khi hàm repr() được gọi trên đối tượng. Nếu có thể, chuỗi được trả về phải là một biểu thức Python hợp lệ có thể được sử dụng để tái tạo lại đối tượng.