Không giống như C++, các lớp trong Python là các đối tượng theo cách riêng của chúng, ngay cả khi không có thể hiện. Chúng chỉ là những không gian tên khép kín. Do đó, miễn là chúng ta có một tham chiếu đến một lớp, chúng ta có thể đặt hoặc thay đổi các thuộc tính của nó bất cứ lúc nào chúng ta muốn. Show Câu lệnh sau tạo một lớp không có thuộc tính nào được đính kèm và trên thực tế, đó là một đối tượng không gian tên trống class Student: pass Tên của lớp này là Sinh viên và nó không kế thừa từ bất kỳ lớp nào khác. Tên lớp thường được viết hoa, nhưng đây chỉ là một quy ước, không phải là một yêu cầu. Mọi thứ trong một lớp đều được thụt lề, giống như mã trong một hàm, câu lệnh if, vòng lặp for hoặc bất kỳ khối mã nào khác. Dòng đầu tiên không thụt lề nằm ngoài lớp Trong mã, pass là câu lệnh không hoạt động. Lớp Sinh viên này không định nghĩa bất kỳ phương thức hoặc thuộc tính nào, nhưng về mặt cú pháp, cần phải có một cái gì đó trong định nghĩa, do đó, câu lệnh pass. Đây là một từ dành riêng cho Python chỉ có nghĩa là di chuyển, không có gì để xem ở đây. Đó là một câu lệnh không làm gì cả, và nó là một trình giữ chỗ tốt khi chúng ta khai thác các hàm hoặc lớp. Câu lệnh vượt qua trong Python giống như một tập hợp rỗng các dấu ngoặc nhọn {} trong Java hoặc C >>> Student.name = "Jack" >>> Student.id = 20001 Sau đó, chúng tôi gắn các thuộc tính cho lớp bằng cách gán tên cho nó bên ngoài lớp. Trong trường hợp này, lớp về cơ bản là một đối tượng có các tên trường gắn liền với nó. >>> print(Student.name) Jack Lưu ý rằng điều này đang hoạt động mặc dù chưa có phiên bản nào của lớp Nhiều lớp được kế thừa từ các lớp khác, nhưng lớp trong ví dụ thì không. Nhiều lớp định nghĩa các phương thức, nhưng lớp này thì không. Không có gì mà một lớp Python nhất thiết phải có, ngoài cái tên. Đặc biệt, các lập trình viên C++ có thể thấy lạ là các lớp Python không có hàm tạo và hàm hủy rõ ràng. Mặc dù không bắt buộc, nhưng các lớp Python có thể có thứ gì đó tương tự như hàm tạo. phương thức __init__() Trong Python, các đối tượng được tạo theo hai bước
Tuy nhiên, rất hiếm khi thực sự cần triển khai __new()__ vì Python xây dựng các đối tượng cho chúng ta. Vì vậy, trong hầu hết các trường hợp, chúng ta thường chỉ triển khai phương thức đặc biệt, __init()__ Hãy tạo một lớp lưu trữ một chuỗi và một số class Student(object): '''Classes can (and should) have docstrings too, just like modules and functions''' def __init__(self, name, id = 20001): self.name = name self.id = id Khi một def xuất hiện bên trong một lớp, nó thường được gọi là một phương thức. Nó tự động nhận một đối số đầu tiên đặc biệt, self, cung cấp một điều khiển ngược lại đối tượng được xử lý. Các phương thức có hai dấu gạch dưới ở đầu và cuối tên là các phương thức đặc biệt Phương thức __init__() được gọi ngay sau khi một thể hiện của lớp được tạo. Sẽ rất hấp dẫn khi gọi đây là hàm tạo của lớp. Nó thực sự hấp dẫn, bởi vì nó giống như một hàm tạo C++, và theo quy ước, phương thức __init__() là phương thức đầu tiên được định nghĩa cho lớp. Nó dường như hoạt động như một hàm tạo vì nó là đoạn mã đầu tiên được thực thi trong một thể hiện mới được tạo của lớp. Tuy nhiên, nó không giống như một hàm tạo, bởi vì đối tượng đã được tạo sẵn vào thời điểm phương thức __init()__ được gọi và chúng ta đã có một tham chiếu hợp lệ cho thể hiện mới của lớp Tham số đầu tiên của phương thức __init()__, self, tương đương với tham số này của C++. Mặc dù chúng ta không cần phải truyền nó vì Python sẽ làm điều đó cho chúng ta, nhưng chúng ta phải đặt self làm tham số đầu tiên của các phương thức không tĩnh. Nhưng bản thân luôn rõ ràng trong Python để truy cập thuộc tính rõ ràng hơn Bản thân luôn là một tham chiếu đến thể hiện hiện tại của lớp. Mặc dù đối số này đóng vai trò của từ dành riêng this trong c ++ hoặc Java, nhưng self không phải là từ dành riêng trong Python, chỉ là một quy ước đặt tên. Tuy nhiên, xin đừng gọi nó là gì khác ngoài bản thân; Khi một phương thức gán cho một thuộc tính self, nó sẽ tạo một thuộc tính trong một thể hiện vì self đề cập đến thể hiện đang được xử lý Để khởi tạo một lớp, chỉ cần gọi lớp đó như thể nó là một hàm, truyền các đối số mà phương thức __init__() yêu cầu. Giá trị trả về sẽ là đối tượng vừa tạo. Trong Python, không có toán tử mới rõ ràng như trong C++ hoặc Java. Vì vậy, chúng ta chỉ cần gọi một lớp như thể nó là một hàm để tạo một thể hiện mới của lớp s = Student(args) Chúng tôi đang tạo một thể hiện của lớp Sinh viên và gán thể hiện mới được tạo cho biến s. Chúng ta đang chuyển một tham số, args, tham số này sẽ kết thúc dưới dạng đối số trong phương thức __init__() của Sinh viên s bây giờ là một thể hiện của lớp Sinh viên. Mọi thể hiện của lớp đều có một thuộc tính tích hợp, __class__, là lớp của đối tượng. Các lập trình viên Java có thể quen thuộc với lớp Class, lớp này chứa các phương thức như getName() và getSuperclass() để lấy thông tin siêu dữ liệu về một đối tượng. Trong Python, loại siêu dữ liệu này có sẵn thông qua các thuộc tính, nhưng ý tưởng thì giống nhau Chúng ta có thể truy cập chuỗi tài liệu của cá thể giống như với một hàm hoặc một mô-đun. Tất cả các phiên bản của một lớp chia sẻ cùng một chuỗi tài liệu Chúng ta có thể sử dụng lớp Sinh viên được định nghĩa ở trên như sau studentA = Student("Jack") studentB = Student("Judy", 10005) Không giống như C++, các thuộc tính của đối tượng Python là công khai, chúng ta có thể truy cập chúng bằng cách sử dụng dấu chấm (. ) nhà điều hành >>>studentA.name 'Jack' >>>studentB.id 10005 Chúng ta cũng có thể gán một giá trị mới cho thuộc tính >>> studentB.id = 80001 >>> studentB.id 80001 Còn việc phá hủy đối tượng thì sao? Hãy xem một ví dụ khác ________số 8Bản thân là gì. id? Sau đó, hãy tạo hai trường hợp >>> s1 = Student() >>> s2 = Student() Ở đây, chúng tôi đã tạo các đối tượng mẫu. Các đối tượng này chỉ là các không gian tên có quyền truy cập vào các thuộc tính của lớp chúng. Hai trường hợp có liên kết trở lại lớp mà chúng được tạo. Nếu chúng ta sử dụng một thể hiện với tên của một thuộc tính của đối tượng lớp, Python sẽ lấy tên từ lớp >>> Student.name = "Jack" >>> Student.id = 200010 Lưu ý rằng cả s1 và s2 đều không có thuộc tính setData() của riêng nó. Vì vậy, Python theo liên kết từ cá thể đến lớp để tìm thuộc tính Trong hàm setData() bên trong Student, giá trị truyền vào được gán cho self. dữ liệu. Trong một phương thức, self tự động tham chiếu đến thể hiện đang được xử lý (s1 hoặc s2). Do đó, các giá trị lưu trữ gán trong không gian tên của cá thể, không phải của lớp Khi chúng ta gọi phương thức display() của lớp để tự in. dữ liệu, chúng ta thấy bản thân. dữ liệu khác nhau trong mỗi trường hợp. Nhưng bản thân tên display() giống nhau trong s1 và s2 >>> Student.name = "Jack" >>> Student.id = 200011 Lưu ý rằng chúng tôi đã lưu trữ các loại đối tượng khác nhau trong thành viên dữ liệu trong mỗi trường hợp. Trong Python, không có khai báo cho các thuộc tính cá thể (thành viên). Chúng ra đời khi chúng được gán giá trị. Thuộc tính có tên data thậm chí không tồn tại trong bộ nhớ cho đến khi nó được gán trong phương thức setData() >>> Student.name = "Jack" >>> Student.id = 200012 Sau đó, chúng tôi tạo các đối tượng thể hiện >>> Student.name = "Jack" >>> Student.id = 200013 Các đối tượng thể hiện chỉ là các không gian tên có quyền truy cập vào các thuộc tính của lớp chúng. Trên thực tế, tại thời điểm này, chúng tôi có ba đối tượng. một lớp và hai trường hợp. Lưu ý rằng cả a và a2 đều không có thuộc tính setData của riêng nó. Tuy nhiên, giá trị được truyền vào setData được gán cho self. dữ liệu. Trong một phương thức, self tự động tham chiếu đến thể hiện đang được xử lý (a hoặc a2). Vì vậy, các bài tập lưu trữ các giá trị trong không gian tên của cá thể, không phải của lớp. Các phương thức phải thông qua đối số self để xử lý cá thể. Chúng ta có thể thấy nó từ đầu ra >>> Student.name = "Jack" >>> Student.id = 200014 Như chúng tôi mong đợi, chúng tôi đã lưu trữ giá trị cho từng đối tượng thể hiện mặc dù chúng tôi đã sử dụng cùng một phương thức, hiển thị. Bản thân đã tạo ra tất cả sự khác biệt. Nó đề cập đến các trường hợp Lớp cha được liệt kê trong ngoặc đơn trong tiêu đề lớp như chúng ta thấy ví dụ bên dưới >>> Student.name = "Jack" >>> Student.id = 200015 MyClassB định nghĩa lại cách hiển thị của lớp cha của nó và nó thay thế thuộc tính display trong khi vẫn kế thừa phương thức setData trong MyClassA như chúng ta thấy bên dưới >>> Student.name = "Jack" >>> Student.id = 200016 Nhưng đối với trường hợp MyClassA vẫn đang sử dụng màn hình, được xác định trước đó trong MyClassA >>> Student.name = "Jack" >>> Student.id = 200017 Quá tải toán tử cho phép các đối tượng chặn và phản hồi các hoạt động. Nó làm cho các giao diện đối tượng nhất quán hơn và nó cũng cho phép các đối tượng lớp hoạt động giống như các phần mềm tích hợp sẵn >>> Student.name = "Jack" >>> Student.id = 200018 MyClassC là một MyClassB và các phiên bản của nó kế thừa phương thức display() từ MyClassB >>> Student.name = "Jack" >>> Student.id = 200019 Khi MyClassC được tạo, một đối số '123' được chuyển. Điều này được chuyển đến đối số d trong hàm tạo __init__ và được gán cho self. dữ liệu. Trên thực tế, MyClassC sắp xếp để đặt thuộc tính dữ liệu tự động tại thời điểm xây dựng. Nó không yêu cầu gọi setdata() từ instance sau này Đối với +, Python chuyển đối tượng thể hiện ở bên trái của đối số self trong __add__ và giá trị ở bên phải cho d2. Đối với print(), Python chuyển đối tượng đang được in thành self trong __str__. Vì vậy, bất kỳ chuỗi nào mà phương thức này trả về đều được coi là chuỗi in cho đối tượng. Bằng cách triển khai __str__, chúng ta có thể sử dụng print để hiển thị các đối tượng của lớp này và chúng ta không phải gọi phương thức display() __add__ tạo và trả về một đối tượng thể hiện mới bằng cách gọi MyClassC. Tuy nhiên, mul thay đổi đối tượng hiện tại tại chỗ bằng cách gán lại thuộc tính self Đây là một ví dụ về một lớp Rectangle với một hàm thành viên trả về diện tích của nó >>> print(Student.name) Jack0 Lưu ý rằng phiên bản này đang sử dụng quyền truy cập thuộc tính trực tiếp cho chiều rộng và chiều cao Chúng tôi có thể đã sử dụng các phương thức setter và getter triển khai sau đây >>> print(Student.name) Jack1 Thuộc tính đối tượng là nơi chúng tôi lưu trữ thông tin của mình và hầu hết các trường hợp, cú pháp sau là đủ >>> print(Student.name) Jack2 Tuy nhiên, có những trường hợp cần linh hoạt hơn. Ví dụ: để xác thực các phương thức setter và getter, chúng ta có thể cần thay đổi toàn bộ mã như thế này >>> print(Student.name) Jack3 Giải pháp cho vấn đề về tính linh hoạt là cho phép chúng tôi chạy mã tự động khi truy cập thuộc tính, nếu cần. Các thuộc tính cho phép chúng tôi định tuyến một quyền truy cập thuộc tính cụ thể (các thao tác get và set của thuộc tính) tới các hàm hoặc phương thức mà chúng tôi cung cấp, cho phép chúng tôi chèn mã để chạy tự động. Thuộc tính được tạo bằng cách gán kết quả của hàm tích hợp cho thuộc tính lớp >>> print(Student.name) Jack4
Nếu chúng ta quay lại mã trước đó và thêm thuộc tính (), thì mã sẽ trông như thế này >>> print(Student.name) Jack5 Chúng ta có thể sử dụng lớp như dưới đây >>> print(Student.name) Jack6 Ví dụ trên chỉ đơn giản là dấu vết truy cập thuộc tính. Tuy nhiên, các thuộc tính thường tự động tính toán giá trị của một thuộc tính khi được tìm nạp, như ví dụ sau đây minh họa >>> print(Student.name) Jack7 Lớp định nghĩa một thuộc tính V được truy cập như thể nó là dữ liệu tĩnh. Tuy nhiên, nó thực sự chạy mã để tính toán giá trị của nó khi được tìm nạp. Khi mã chạy, giá trị được lưu trữ trong phiên bản dưới dạng thông tin trạng thái, nhưng bất cứ khi nào chúng tôi truy xuất nó thông qua thuộc tính được quản lý, giá trị của nó sẽ tự động bình phương >>> print(Student.name) Jack8 Một lần nữa, lưu ý rằng quá trình tìm nạp tính bình phương dữ liệu của cá thể Quá tải toán tử. 2. 6 __cmp__() (Đã xóa sau 3. 0) By implementing __cmp__() method, all of the comparison operators(<, ==, !=, >, etc.) will work. Vì vậy, hãy thêm phần sau vào lớp Hình chữ nhật của chúng ta >>> print(Student.name) Jack9 Lưu ý rằng chúng tôi đã sử dụng chức năng cmp() tích hợp để triển khai __cmp__. Hàm cmp() trả về -1 nếu đối số thứ nhất nhỏ hơn đối số thứ hai, 0 nếu chúng bằng nhau và 1 nếu đối số thứ nhất lớn hơn đối số thứ hai Đối với Trăn 3. 0, chúng tôi nhận được TypeError. loại không thể sắp xếp. Vì vậy, chúng ta cần sử dụng các phương thức cụ thể vì các hàm tích hợp __cmp__() và cmp() đã bị xóa trong Python 3. 0 Quá tải toán tử. __str__ __str__ là nạp chồng toán tử được sử dụng phổ biến thứ 2 trong Python sau __init__. __str__ được chạy tự động bất cứ khi nào một phiên bản được chuyển đổi thành chuỗi in của nó Hãy sử dụng ví dụ trước class Student(object): '''Classes can (and should) have docstrings too, just like modules and functions''' def __init__(self, name, id = 20001): self.name = name self.id = id0 Nếu chúng ta in thể hiện, nó sẽ hiển thị toàn bộ đối tượng như hình bên dưới class Student(object): '''Classes can (and should) have docstrings too, just like modules and functions''' def __init__(self, name, id = 20001): self.name = name self.id = id1 Nó hiển thị tên lớp của đối tượng và địa chỉ của nó trong bộ nhớ, về cơ bản là vô dụng ngoại trừ một mã định danh duy nhất Vì vậy, hãy thêm phương thức __str__ class Student(object): '''Classes can (and should) have docstrings too, just like modules and functions''' def __init__(self, name, id = 20001): self.name = name self.id = id2 Đoạn mã trên mở rộng lớp của chúng tôi để cung cấp một màn hình tùy chỉnh liệt kê các thuộc tính khi các phiên bản của lớp chúng tôi được hiển thị tổng thể, thay vì dựa vào màn hình ít hữu ích hơn. Lưu ý rằng chúng tôi đang thực hiện định dạng chuỗi % để tạo chuỗi hiển thị trong __str__ Sự khác biệt giữa __str__ và __repr__ không quá rõ ràng Khi chúng ta sử dụng print, Python sẽ tìm phương thức __str__ trong lớp của chúng ta. Nếu nó tìm thấy một, nó sẽ gọi nó. Nếu không, nó sẽ tìm phương thức __repr__ và gọi nó. Nếu không thể tìm thấy, nó sẽ tạo một biểu diễn bên trong đối tượng của chúng ta class Student(object): '''Classes can (and should) have docstrings too, just like modules and functions''' def __init__(self, name, id = 20001): self.name = name self.id = id3 Không có nhiều thông tin từ print(x) và chỉ lặp lại đối tượng x. Đó là lý do tại sao chúng tôi tùy chỉnh lớp bằng cách sử dụng __str__ class Student(object): '''Classes can (and should) have docstrings too, just like modules and functions''' def __init__(self, name, id = 20001): self.name = name self.id = id4 Nhưng không phải khi chúng ta sử dụng print(myObjecs). Lưu ý rằng các phiên bản nằm trong danh sách class Student(object): '''Classes can (and should) have docstrings too, just like modules and functions''' def __init__(self, name, id = 20001): self.name = name self.id = id5 Vì vậy, chúng ta cần xác định __repr__. class Student(object): '''Classes can (and should) have docstrings too, just like modules and functions''' def __init__(self, name, id = 20001): self.name = name self.id = id6 Trong cuốn sách của mình, Learning Python, Mark Lutz đã tóm tắt như sau. sys. argv là danh sách các đối số được truyền cho chương trình Python.
class Student(object): '''Classes can (and should) have docstrings too, just like modules and functions''' def __init__(self, name, id = 20001): self.name = name self.id = id7 Nếu chúng tôi chạy nó có hoặc không có bất kỳ đối số nào, chúng tôi sẽ nhận được kết quả bên dưới class Student(object): '''Classes can (and should) have docstrings too, just like modules and functions''' def __init__(self, name, id = 20001): self.name = name self.id = id8 getopt. getopt(args, options[, long_options]) getopt. getopt() phân tích các tùy chọn dòng lệnh và danh sách tham số. args là danh sách đối số được phân tích cú pháp, không có tham chiếu hàng đầu đến chương trình đang chạy. Thông thường, điều này có nghĩa là sys. argv[1. ]. tùy chọn là chuỗi các chữ cái tùy chọn mà tập lệnh muốn nhận dạng, với các tùy chọn yêu cầu đối số theo sau là dấu hai chấm (. ) long_options, nếu được chỉ định, phải là danh sách các chuỗi có tên của các tùy chọn dài sẽ được hỗ trợ. Các ký tự -- hàng đầu không nên được bao gồm trong tên tùy chọn. Các tùy chọn dài yêu cầu đối số phải được theo sau bởi dấu bằng (=). Đối số tùy chọn không được hỗ trợ. Để chỉ chấp nhận các tùy chọn dài, các tùy chọn phải là một chuỗi rỗng. Các tùy chọn dài trên dòng lệnh có thể được nhận ra miễn là chúng cung cấp tiền tố của tên tùy chọn khớp chính xác với một trong các tùy chọn được chấp nhận. Giá trị trả về bao gồm hai phần tử
-từ http. // tài liệu. con trăn. org/2/library/getopt. html. class Student(object): '''Classes can (and should) have docstrings too, just like modules and functions''' def __init__(self, name, id = 20001): self.name = name self.id = id9 Nếu chúng tôi chạy với hai tùy chọn tệp dài s = Student(args)0 Với các tùy chọn ngắn s = Student(args)1 Lưu ý rằng tùy chọn dài không nhất thiết phải được khớp hoàn toàn s = Student(args)2 Python chạy phương thức __call__ khi một thể hiện được gọi dưới dạng hàm. Điều này hữu ích hơn khi chúng tôi thực hiện một số công việc giao tiếp với các chức năng mong đợi API. Trên hết, chúng ta cũng có thể giữ lại thông tin trạng thái như chúng ta thấy trong các ví dụ sau của phần này Nó được cho là phương thức nạp chồng toán tử được sử dụng phổ biến thứ ba, sau __init__ và __str__ và __repr__ theo Mark Lutz (Học Python) Đây là một ví dụ với phương thức __call__ trong một lớp. Phương thức __call__ chỉ cần in ra các đối số mà nó nhận được thông qua từ khóa args s = Student(args)3 Như một ví dụ khác với các đối số hỗn hợp hơn một chút s = Student(args)4 Mặc dù phương thức __call__ cho phép chúng ta sử dụng các thể hiện của lớp để mô phỏng các hàm như chúng ta đã thấy trong các ví dụ trên, nhưng có một cách sử dụng khác của phương thức __call__. chúng tôi có thể giữ lại thông tin trạng thái Thể hiện của 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.
__ lớp __ trong Python là gì?__class__ là một thuộc tính trên đối tượng đề cập đến lớp mà đối tượng được tạo ra từ đó . một. __lớp__ # Đầu ra.
Tự __ lớp __ __ tên __ trong Python là gì?chính mình. __class__ là tham chiếu đến loại của phiên bản hiện tại . Đưa ra một ngoại lệ ở đây cũng giống như sử dụng một câu lệnh khẳng định ở đâu đó trong mã của bạn, nó bảo vệ bạn khỏi những sai lầm ngớ ngẩn. type() nên được ưu tiên hơn self.
Thể hiện của một lớp là gì?Một thể hiện của lớp là một đối tượng . Nó còn được gọi là một đối tượng lớp hoặc thể hiện của lớp. Như vậy, khởi tạo có thể được gọi là xây dựng. Bất cứ khi nào các giá trị thay đổi từ đối tượng này sang đối tượng khác, chúng được gọi là biến thể hiện. |