Loại tự trong python là gì?

Nó thực sự không phải là bất thường trong Python, hãy xem xét

cat1 = Cat['Andy', 2]
cat2 = Cat['Phoebe', 3]
2, chỉ gọi
cat1 = Cat['Andy', 2]
cat2 = Cat['Phoebe', 3]
3 hoặc
cat1 = Cat['Andy', 2]
cat2 = Cat['Phoebe', 3]
4, chỉ gọi
cat1 = Cat['Andy', 2]
cat2 = Cat['Phoebe', 3]
5. Python ưu tiên sử dụng các chức năng tích hợp sẵn cho các chức năng phổ biến mà bạn có khả năng sử dụng trên một loạt các lớp và thường triển khai các chức năng này bằng cách gọi các phương thức
cat1 = Cat['Andy', 2]
cat2 = Cat['Phoebe', 3]
6

Nếu bạn đã lập trình bằng Python [lập trình hướng đối tượng] một thời gian, thì bạn chắc chắn đã bắt gặp các phương thức có tham số đầu tiên là

cat1 = Cat['Andy', 2]
cat2 = Cat['Phoebe', 3]
3

Trước tiên chúng ta hãy cố gắng hiểu tham số tự định kỳ này là gì

Bản thân trong Python là gì?

Trong lập trình hướng đối tượng, bất cứ khi nào chúng ta định nghĩa các phương thức cho một lớp, chúng ta sử dụng

cat1 = Cat['Andy', 2]
cat2 = Cat['Phoebe', 3]
3 làm tham số đầu tiên trong mỗi trường hợp. Hãy xem định nghĩa của một lớp có tên là
cat1 = Cat['Andy', 2]
cat2 = Cat['Phoebe', 3]
5

class Cat:
    def __init__[self, name, age]:
        self.name = name
        self.age = age

    def info[self]:
        print[f"I am a cat. My name is {self.name}. I am {self.age} years old."]

    def make_sound[self]:
        print["Meow"]

Trong trường hợp này, tất cả các phương thức, kể cả

cat1 = Cat['Andy', 2]
cat2 = Cat['Phoebe', 3]
6, đều có tham số đầu tiên là
cat1 = Cat['Andy', 2]
cat2 = Cat['Phoebe', 3]
3

Chúng ta biết rằng lớp là bản thiết kế cho các đối tượng. Bản thiết kế này có thể được sử dụng để tạo ra nhiều đối tượng. Hãy tạo hai đối tượng khác nhau từ lớp trên

cat1 = Cat['Andy', 2]
cat2 = Cat['Phoebe', 3]

Từ khóa

cat1 = Cat['Andy', 2]
cat2 = Cat['Phoebe', 3]
3 được sử dụng để đại diện cho một thể hiện [đối tượng] của lớp đã cho. Trong trường hợp này, hai đối tượng
cat1 = Cat['Andy', 2]
cat2 = Cat['Phoebe', 3]
5
class Point[object]:
    def __init__[self,x = 0,y = 0]:
        self.x = x
        self.y = y

    def distance[self]:
        """Find distance from origin"""
        return [self.x**2 + self.y**2] ** 0.5
0 và
class Point[object]:
    def __init__[self,x = 0,y = 0]:
        self.x = x
        self.y = y

    def distance[self]:
        """Find distance from origin"""
        return [self.x**2 + self.y**2] ** 0.5
1 có thuộc tính riêng là
class Point[object]:
    def __init__[self,x = 0,y = 0]:
        self.x = x
        self.y = y

    def distance[self]:
        """Find distance from origin"""
        return [self.x**2 + self.y**2] ** 0.5
2 và
class Point[object]:
    def __init__[self,x = 0,y = 0]:
        self.x = x
        self.y = y

    def distance[self]:
        """Find distance from origin"""
        return [self.x**2 + self.y**2] ** 0.5
3. Nếu không có đối số tự, thì cùng một lớp không thể chứa thông tin cho cả hai đối tượng này

Tuy nhiên, do lớp chỉ là một bản thiết kế nên

cat1 = Cat['Andy', 2]
cat2 = Cat['Phoebe', 3]
3 cho phép truy cập vào các thuộc tính và phương thức của từng đối tượng trong python. Điều này cho phép mỗi đối tượng có các thuộc tính và phương thức riêng. Do đó, thậm chí rất lâu trước khi tạo các đối tượng này, chúng tôi tham chiếu các đối tượng là
cat1 = Cat['Andy', 2]
cat2 = Cat['Phoebe', 3]
3 trong khi định nghĩa lớp

Tại sao bản thân được xác định rõ ràng mọi lúc?

Ngay cả khi chúng ta hiểu cách sử dụng của

cat1 = Cat['Andy', 2]
cat2 = Cat['Phoebe', 3]
3, nó vẫn có vẻ kỳ lạ, đặc biệt là đối với các lập trình viên đến từ các ngôn ngữ khác, rằng
cat1 = Cat['Andy', 2]
cat2 = Cat['Phoebe', 3]
3 được truyền dưới dạng tham số một cách rõ ràng mỗi khi chúng ta định nghĩa một phương thức. Như The Zen of Python đã nói, "Rõ ràng tốt hơn ngầm"

Vì vậy, tại sao chúng ta cần phải làm điều này? . Chúng ta có một lớp

class Point[object]:
    def __init__[self,x = 0,y = 0]:
        self.x = x
        self.y = y

    def distance[self]:
        """Find distance from origin"""
        return [self.x**2 + self.y**2] ** 0.5
8 định nghĩa một phương thức
class Point[object]:
    def __init__[self,x = 0,y = 0]:
        self.x = x
        self.y = y

    def distance[self]:
        """Find distance from origin"""
        return [self.x**2 + self.y**2] ** 0.5
9 để tính khoảng cách từ gốc tọa độ

class Point[object]:
    def __init__[self,x = 0,y = 0]:
        self.x = x
        self.y = y

    def distance[self]:
        """Find distance from origin"""
        return [self.x**2 + self.y**2] ** 0.5

Bây giờ chúng ta hãy khởi tạo lớp này và tìm khoảng cách

cat1 = Cat['Andy', 2]
cat2 = Cat['Phoebe', 3]
0

Trong ví dụ trên,

cat1 = Cat['Andy', 2]
cat2 = Cat['Phoebe', 3]
00 xác định ba tham số nhưng chúng tôi chỉ chuyển hai tham số [6 và 8]. Tương tự,
cat1 = Cat['Andy', 2]
cat2 = Cat['Phoebe', 3]
01 yêu cầu một đối số nhưng không có đối số nào được thông qua. Tại sao Python không phàn nàn về số đối số này không khớp?

Điều gì xảy ra trong nội bộ?

cat1 = Cat['Andy', 2]
cat2 = Cat['Phoebe', 3]
02 và
cat1 = Cat['Andy', 2]
cat2 = Cat['Phoebe', 3]
03 trong ví dụ trên là khác nhau và không hoàn toàn giống nhau

cat1 = Cat['Andy', 2]
cat2 = Cat['Phoebe', 3]
5

Chúng ta có thể thấy rằng cái đầu tiên là một hàm và cái thứ hai là một phương thức. Một điều đặc biệt về các phương thức [trong Python] là chính đối tượng được truyền làm đối số đầu tiên cho hàm tương ứng

Trong trường hợp của ví dụ trên, cuộc gọi phương thức

cat1 = Cat['Andy', 2]
cat2 = Cat['Phoebe', 3]
04 thực sự tương đương với
cat1 = Cat['Andy', 2]
cat2 = Cat['Phoebe', 3]
05

Nói chung, khi chúng ta gọi một phương thức với một số đối số, hàm lớp tương ứng được gọi bằng cách đặt đối tượng của phương thức trước đối số đầu tiên. Vì vậy, bất cứ điều gì như

cat1 = Cat['Andy', 2]
cat2 = Cat['Phoebe', 3]
06 trở thành
cat1 = Cat['Andy', 2]
cat2 = Cat['Phoebe', 3]
07. Quá trình gọi là tự động trong khi quá trình nhận thì không [rõ ràng]

Đây là lý do tham số đầu tiên của hàm trong lớp phải là chính đối tượng đó. Viết tham số này là

cat1 = Cat['Andy', 2]
cat2 = Cat['Phoebe', 3]
3 chỉ là một quy ước. Nó không phải là từ khóa và không có ý nghĩa đặc biệt trong Python. Chúng tôi có thể sử dụng các tên khác [như
cat1 = Cat['Andy', 2]
cat2 = Cat['Phoebe', 3]
09] nhưng điều đó không được khuyến khích. Hầu hết các nhà phát triển đều phản đối việc sử dụng các tên khác với tên
cat1 = Cat['Andy', 2]
cat2 = Cat['Phoebe', 3]
3 và làm giảm khả năng đọc của mã [Khả năng đọc được tính]

Bản ngã có thể tránh được

Bây giờ bạn đã rõ rằng bản thân đối tượng [thể hiện] được truyền tự động dưới dạng đối số đầu tiên. Hành vi ngầm định này có thể tránh được khi tạo một phương thức tĩnh. Xét ví dụ đơn giản sau

class Cat:
    def __init__[self, name, age]:
        self.name = name
        self.age = age

    def info[self]:
        print[f"I am a cat. My name is {self.name}. I am {self.age} years old."]

    def make_sound[self]:
        print["Meow"]
3

Ở đây,

cat1 = Cat['Andy', 2]
cat2 = Cat['Phoebe', 3]
51 là một hàm trang trí làm cho
cat1 = Cat['Andy', 2]
cat2 = Cat['Phoebe', 3]
52 trở nên tĩnh. Hãy để chúng tôi khởi tạo lớp này và gọi phương thức

class Cat:
    def __init__[self, name, age]:
        self.name = name
        self.age = age

    def info[self]:
        print[f"I am a cat. My name is {self.name}. I am {self.age} years old."]

    def make_sound[self]:
        print["Meow"]
6

Từ ví dụ trên, chúng ta có thể thấy rằng hành vi ngầm truyền đối tượng làm đối số đầu tiên đã được tránh khi sử dụng một phương thức tĩnh. Nói chung, các phương thức tĩnh hoạt động giống như các hàm cũ đơn giản [Vì tất cả các đối tượng của một lớp đều chia sẻ các phương thức tĩnh]

class Cat:
    def __init__[self, name, age]:
        self.name = name
        self.age = age

    def info[self]:
        print[f"I am a cat. My name is {self.name}. I am {self.age} years old."]

    def make_sound[self]:
        print["Meow"]
7

Tự ở đây để ở lại

cat1 = Cat['Andy', 2]
cat2 = Cat['Phoebe', 3]
3 rõ ràng không phải là duy nhất đối với Python. Ý tưởng này được mượn từ Modula-3. Sau đây là trường hợp sử dụng khi nó trở nên hữu ích

Không có khai báo biến rõ ràng trong Python. Họ bắt đầu hành động trong nhiệm vụ đầu tiên. Việc sử dụng

cat1 = Cat['Andy', 2]
cat2 = Cat['Phoebe', 3]
3 giúp dễ dàng phân biệt giữa các thuộc tính [và phương thức] của thể hiện với các biến cục bộ

Trong ví dụ đầu tiên, bản thân. x là một thuộc tính thể hiện trong khi x là một biến cục bộ. Chúng không giống nhau và chúng nằm trong các không gian tên khác nhau

Nhiều người đã đề xuất biến self thành một từ khóa trong Python, như

cat1 = Cat['Andy', 2]
cat2 = Cat['Phoebe', 3]
55 trong C++ và Java. Điều này sẽ loại bỏ việc sử dụng dư thừa của
cat1 = Cat['Andy', 2]
cat2 = Cat['Phoebe', 3]
3 rõ ràng từ danh sách tham số chính thức trong các phương thức

Mặc dù ý tưởng này có vẻ hứa hẹn nhưng nó sẽ không xảy ra. Ít nhất là không phải trong tương lai gần. Lý do chính là khả năng tương thích ngược. Đây là một blog của chính người tạo ra Python giải thích lý do tại sao bản thân rõ ràng phải ở lại

__init__[] không phải là hàm tạo

Một kết luận quan trọng có thể được rút ra từ thông tin cho đến nay là phương thức

cat1 = Cat['Andy', 2]
cat2 = Cat['Phoebe', 3]
00 không phải là hàm tạo. Nhiều lập trình viên Python ngây thơ bị nhầm lẫn với nó vì
cat1 = Cat['Andy', 2]
cat2 = Cat['Phoebe', 3]
00 được gọi khi chúng ta tạo một đối tượng

Kiểm tra kỹ hơn sẽ thấy rằng tham số đầu tiên trong

cat1 = Cat['Andy', 2]
cat2 = Cat['Phoebe', 3]
00 chính là đối tượng [đối tượng đã tồn tại]. Hàm
cat1 = Cat['Andy', 2]
cat2 = Cat['Phoebe', 3]
00 được gọi ngay sau khi đối tượng được tạo và được sử dụng để khởi tạo nó

Về mặt kỹ thuật, hàm tạo là một phương thức tự tạo đối tượng. Trong Python, phương thức này là

class Cat:
    def __init__[self, name, age]:
        self.name = name
        self.age = age

    def info[self]:
        print[f"I am a cat. My name is {self.name}. I am {self.age} years old."]

    def make_sound[self]:
        print["Meow"]
31. Một chữ ký phổ biến của phương pháp này là

cat1 = Cat['Andy', 2]
cat2 = Cat['Phoebe', 3]
7

Khi

class Cat:
    def __init__[self, name, age]:
        self.name = name
        self.age = age

    def info[self]:
        print[f"I am a cat. My name is {self.name}. I am {self.age} years old."]

    def make_sound[self]:
        print["Meow"]
31 được gọi, chính lớp đó sẽ tự động được chuyển thành đối số đầu tiên [
class Cat:
    def __init__[self, name, age]:
        self.name = name
        self.age = age

    def info[self]:
        print[f"I am a cat. My name is {self.name}. I am {self.age} years old."]

    def make_sound[self]:
        print["Meow"]
33]

Một lần nữa, giống như bản thân, cls chỉ là một quy ước đặt tên. Ngoài ra, *args và **kwargs được sử dụng để lấy số lượng đối số tùy ý trong khi gọi phương thức trong Python

Một số điều quan trọng cần nhớ khi triển khai

class Cat:
    def __init__[self, name, age]:
        self.name = name
        self.age = age

    def info[self]:
        print[f"I am a cat. My name is {self.name}. I am {self.age} years old."]

    def make_sound[self]:
        print["Meow"]
31 là

  • class Cat:
        def __init__[self, name, age]:
            self.name = name
            self.age = age
    
        def info[self]:
            print[f"I am a cat. My name is {self.name}. I am {self.age} years old."]
    
        def make_sound[self]:
            print["Meow"]
    31 luôn được gọi trước
    cat1 = Cat['Andy', 2]
    cat2 = Cat['Phoebe', 3]
    00
  • Đối số đầu tiên là chính lớp đó được truyền ngầm
  • Luôn trả về một đối tượng hợp lệ từ
    class Cat:
        def __init__[self, name, age]:
            self.name = name
            self.age = age
    
        def info[self]:
            print[f"I am a cat. My name is {self.name}. I am {self.age} years old."]
    
        def make_sound[self]:
            print["Meow"]
    31. Không bắt buộc, nhưng công dụng chính của nó là tạo và trả về một đối tượng

Hãy xem một ví dụ

cat1 = Cat['Andy', 2]
cat2 = Cat['Phoebe', 3]
4

Bây giờ, hãy khởi tạo nó

cat1 = Cat['Andy', 2]
cat2 = Cat['Phoebe', 3]
0

Ví dụ này minh họa rằng

class Cat:
    def __init__[self, name, age]:
        self.name = name
        self.age = age

    def info[self]:
        print[f"I am a cat. My name is {self.name}. I am {self.age} years old."]

    def make_sound[self]:
        print["Meow"]
31 được gọi trước
cat1 = Cat['Andy', 2]
cat2 = Cat['Phoebe', 3]
00. Chúng ta cũng có thể thấy rằng tham số cls trong
class Cat:
    def __init__[self, name, age]:
        self.name = name
        self.age = age

    def info[self]:
        print[f"I am a cat. My name is {self.name}. I am {self.age} years old."]

    def make_sound[self]:
        print["Meow"]
31 chính là lớp đó [
class Point[object]:
    def __init__[self,x = 0,y = 0]:
        self.x = x
        self.y = y

    def distance[self]:
        """Find distance from origin"""
        return [self.x**2 + self.y**2] ** 0.5
8]. Cuối cùng, đối tượng được tạo bằng cách gọi phương thức
class Cat:
    def __init__[self, name, age]:
        self.name = name
        self.age = age

    def info[self]:
        print[f"I am a cat. My name is {self.name}. I am {self.age} years old."]

    def make_sound[self]:
        print["Meow"]
31 trên lớp cơ sở đối tượng

Trong Python,

class Cat:
    def __init__[self, name, age]:
        self.name = name
        self.age = age

    def info[self]:
        print[f"I am a cat. My name is {self.name}. I am {self.age} years old."]

    def make_sound[self]:
        print["Meow"]
63 là lớp cơ sở mà tất cả các lớp khác được dẫn xuất từ ​​đó. Trong ví dụ trên, chúng tôi đã thực hiện việc này bằng cách sử dụng super[]

Sử dụng __new__ hay __init__?

Bạn có thể đã thấy

cat1 = Cat['Andy', 2]
cat2 = Cat['Phoebe', 3]
00 rất thường xuyên nhưng việc sử dụng
class Cat:
    def __init__[self, name, age]:
        self.name = name
        self.age = age

    def info[self]:
        print[f"I am a cat. My name is {self.name}. I am {self.age} years old."]

    def make_sound[self]:
        print["Meow"]
31 rất hiếm. Điều này là do hầu hết thời gian bạn không cần ghi đè lên nó. Nói chung,
cat1 = Cat['Andy', 2]
cat2 = Cat['Phoebe', 3]
00 được sử dụng để khởi tạo đối tượng mới được tạo trong khi
class Cat:
    def __init__[self, name, age]:
        self.name = name
        self.age = age

    def info[self]:
        print[f"I am a cat. My name is {self.name}. I am {self.age} years old."]

    def make_sound[self]:
        print["Meow"]
31 được sử dụng để kiểm soát cách tạo đối tượng

Chúng ta cũng có thể sử dụng

class Cat:
    def __init__[self, name, age]:
        self.name = name
        self.age = age

    def info[self]:
        print[f"I am a cat. My name is {self.name}. I am {self.age} years old."]

    def make_sound[self]:
        print["Meow"]
31 để khởi tạo các thuộc tính của một đối tượng, nhưng theo logic thì nó phải nằm trong
cat1 = Cat['Andy', 2]
cat2 = Cat['Phoebe', 3]
00

Tuy nhiên, một cách sử dụng thực tế của

class Cat:
    def __init__[self, name, age]:
        self.name = name
        self.age = age

    def info[self]:
        print[f"I am a cat. My name is {self.name}. I am {self.age} years old."]

    def make_sound[self]:
        print["Meow"]
31 có thể là hạn chế số lượng đối tượng được tạo từ một lớp

Giả sử chúng ta muốn có một lớp

class Cat:
    def __init__[self, name, age]:
        self.name = name
        self.age = age

    def info[self]:
        print[f"I am a cat. My name is {self.name}. I am {self.age} years old."]

    def make_sound[self]:
        print["Meow"]
71 để tạo các thể hiện đại diện cho bốn đỉnh của một hình vuông. Chúng ta có thể kế thừa từ lớp trước
class Point[object]:
    def __init__[self,x = 0,y = 0]:
        self.x = x
        self.y = y

    def distance[self]:
        """Find distance from origin"""
        return [self.x**2 + self.y**2] ** 0.5
8 [ví dụ thứ hai trong bài viết này] và sử dụng
class Cat:
    def __init__[self, name, age]:
        self.name = name
        self.age = age

    def info[self]:
        print[f"I am a cat. My name is {self.name}. I am {self.age} years old."]

    def make_sound[self]:
        print["Meow"]
31 để triển khai hạn chế này. Đây là một ví dụ để hạn chế một lớp chỉ có bốn trường hợp

__ init __[ bản thân là gì?

__init__ là hàm tạo cho một lớp . Tham số self đề cập đến thể hiện của đối tượng [như thế này trong C++].

Bản thân trong Python có phải là một con trỏ không?

Biến p trỏ đến một đối tượng Point [hãy nhớ rằng biến là con trỏ trong Python]. Biến self đó trong lệnh gọi phương thức của chúng ta trỏ đến cùng một đối tượng chính xác. Vì vậy, self thực sự chỉ là một biến trỏ đến thể hiện của lớp mà chúng ta hiện đang làm việc với .

__ str __[ self trong Python là gì?

Trăn __str__[] . Phương thức này được gọi khi hàm print[] hoặc str[] được gọi trên một đối tượng. This method returns the string representation of the object. This method is called when print[] or str[] function is invoked on an object.

Chủ Đề