Các ví dụ trên là các lớp và đối tượng ở dạng đơn giản nhất và không thực sự hữu ích trong các ứng dụng thực tế
Để hiểu ý nghĩa của các lớp, chúng ta phải hiểu hàm __init__[] tích hợp sẵn
Tất cả các lớp đều có một hàm gọi là __init__[], hàm này luôn được thực thi khi lớp bắt đầu
Sử dụng hàm __init__[] để gán giá trị cho thuộc tính đối tượng hoặc các thao tác khác cần thực hiện khi đối tượng được tạo
Thí dụ
Tạo một lớp tên là Person, sử dụng hàm __init__[] để gán giá trị cho tên và tuổi
lớp người
def __init__[bản thân, tên, tuổi]
bản thân. tên = tên
bản thân. tuổi = tuổi
p1 = Người["John", 36]
in[p1. Tên]
in[p1. tuổi]
Ghi chú. Hàm __init__[]
được gọi tự động mỗi khi lớp được sử dụng để tạo một đối tượng mới
Hàm __str__[]
Hàm __str__[] kiểm soát những gì sẽ được trả về khi đối tượng lớp được biểu diễn dưới dạng chuỗi
Nếu hàm __str__[] không được đặt, thì biểu diễn chuỗi của đối tượng được trả về
Thí dụ
Biểu diễn chuỗi của một đối tượng KHÔNG CÓ hàm __str__[]
lớp người
def __init__[bản thân, tên, tuổi]
bản thân. tên = tên
bản thân. tuổi = tuổi
p1 = Người["John", 36]
bản in[p1]
Tự mình thử »Thí dụ
Biểu diễn chuỗi của một đối tượng VỚI hàm __str__[]
lớp người
def __init__[bản thân, tên, tuổi]
bản thân. tên = tên
bản thân. tuổi = tuổi
def __str__[bản thân]
trả về f"{tự. tên}[{bản thân. tuổi}]"
p1 = Người["John", 36]
bản in[p1]
Tự mình thử »phương pháp đối tượng
Các đối tượng cũng có thể chứa các phương thức. Các phương thức trong các đối tượng là các chức năng thuộc về đối tượng
Hãy để chúng tôi tạo một phương thức trong lớp Person
Thí dụ
Chèn một hàm in lời chào và thực hiện nó trên đối tượng p1
lớp người
def __init__[bản thân, tên, tuổi]
bản thân. tên = tên
bản thân. tuổi = tuổi
def myfunc[bản thân]
print["Xin chào, tên tôi là " + self. Tên]
p1 = Người["John", 36]
p1. myfunc[]
Ghi chú. Tham số self
là tham chiếu đến phiên bản hiện tại của lớp và được sử dụng để truy cập các biến thuộc về lớp
Tham số bản thân
Tham số self
là tham chiếu đến phiên bản hiện tại của lớp và được sử dụng để truy cập các biến thuộc về lớp
Nó không nhất thiết phải được đặt tên là self
, bạn có thể gọi nó là gì tùy thích, nhưng nó phải là tham số đầu tiên của bất kỳ chức năng nào trong lớp
Thí dụ
Sử dụng các từ mysillyobject và abc thay vì self
lớp người
def __init__[mysillyobject, tên, tuổi]
đối tượng của tôi. tên = tên
đối tượng của tôi. tuổi = tuổi
xác định myfunc [abc]
print["Xin chào, tên tôi là " + abc. Tên]
p1 = Người["John", 36]
p1. myfunc[]
Sửa đổi thuộc tính đối tượng
Bạn có thể sửa đổi các thuộc tính trên các đối tượng như thế này
Xóa thuộc tính đối tượng
Bạn có thể xóa các thuộc tính trên các đối tượng bằng cách sử dụng từ khóa del
Xóa đối tượng
Bạn có thể xóa các đối tượng bằng cách sử dụng từ khóa del
Tuyên bố vượt qua
Định nghĩa class
không thể để trống, nhưng nếu vì lý do nào đó bạn có định nghĩa class
không có nội dung, hãy đặt câu lệnh pass
để tránh mắc lỗi
Thuật ngữ siêu lập trình đề cập đến khả năng một chương trình có kiến thức hoặc thao tác với chính nó. Python hỗ trợ một dạng lập trình siêu dữ liệu cho các lớp được gọi là siêu dữ liệu
Siêu dữ liệu là một khái niệm OOP bí truyền, ẩn đằng sau hầu như tất cả mã Python. Bạn đang sử dụng chúng cho dù bạn có biết hay không. Phần lớn, bạn không cần phải biết về nó. Hầu hết các lập trình viên Python hiếm khi phải suy nghĩ về siêu dữ liệu
Tuy nhiên, khi có nhu cầu, Python cung cấp một khả năng mà không phải ngôn ngữ hướng đối tượng nào cũng hỗ trợ. bạn có thể hiểu rõ hơn và xác định siêu dữ liệu tùy chỉnh. Việc sử dụng các siêu dữ liệu tùy chỉnh có phần gây tranh cãi, như được đề xuất bởi trích dẫn sau đây của Tim Peters, bậc thầy về Python, tác giả của Zen of Python
“Siêu dữ liệu là phép thuật sâu sắc hơn 99% người dùng nên lo lắng về. Nếu bạn tự hỏi liệu bạn có cần chúng hay không, thì bạn không cần [những người thực sự cần chúng biết chắc chắn rằng họ cần chúng và không cần lời giải thích tại sao]. ”
—Tim Peters
Có những Pythonistas [như những người hâm mộ Python được biết đến] tin rằng bạn không bao giờ nên sử dụng siêu dữ liệu tùy chỉnh. Điều đó có thể hơi xa, nhưng có lẽ đúng là các siêu dữ liệu tùy chỉnh hầu như không cần thiết. Nếu không rõ ràng là một vấn đề cần đến chúng, thì nó có thể sẽ rõ ràng và dễ đọc hơn nếu được giải quyết theo cách đơn giản hơn
Tuy nhiên, việc hiểu các siêu dữ liệu Python là đáng giá, bởi vì nó dẫn đến sự hiểu biết tốt hơn về phần bên trong của các lớp Python nói chung. Bạn không bao giờ biết. một ngày nào đó bạn có thể thấy mình ở một trong những tình huống mà bạn chỉ biết rằng một siêu dữ liệu tùy chỉnh là thứ bạn muốn
Nhận được thông báo. Đừng bỏ lỡ phần tiếp theo của hướng dẫn này—Nhấp vào đây để tham gia Bản tin Python thực và bạn sẽ biết khi phần tiếp theo ra mắt
Kiểu cũ vs. Lớp học kiểu mới
Trong lĩnh vực Python, một lớp có thể là một trong hai loại. Không có thuật ngữ chính thức nào được quyết định, vì vậy chúng được gọi một cách không chính thức là lớp học kiểu cũ và kiểu mới
Loại bỏ các quảng cáoLớp học kiểu cũ
Với các lớp kiểu cũ, lớp và loại không hoàn toàn giống nhau. Một thể hiện của một lớp kiểu cũ luôn được triển khai từ một kiểu dựng sẵn duy nhất có tên là
>>> n = 5
>>> d = { 'x' : 1, 'y' : 2 }
>>> class Foo:
.. pass
...
>>> x = Foo[]
>>> for obj in [n, d, x]:
.. print[type[obj] is obj.__class__]
...
True
True
True
5. Nếu >>> n = 5
>>> d = { 'x' : 1, 'y' : 2 }
>>> class Foo:
.. pass
...
>>> x = Foo[]
>>> for obj in [n, d, x]:
.. print[type[obj] is obj.__class__]
...
True
True
True
6 là một thể hiện của lớp kiểu cũ, thì >>> n = 5
>>> d = { 'x' : 1, 'y' : 2 }
>>> class Foo:
.. pass
...
>>> x = Foo[]
>>> for obj in [n, d, x]:
.. print[type[obj] is obj.__class__]
...
True
True
True
7 chỉ định lớp đó, nhưng >>> n = 5
>>> d = { 'x' : 1, 'y' : 2 }
>>> class Foo:
.. pass
...
>>> x = Foo[]
>>> for obj in [n, d, x]:
.. print[type[obj] is obj.__class__]
...
True
True
True
8 luôn là >>> n = 5
>>> d = { 'x' : 1, 'y' : 2 }
>>> class Foo:
.. pass
...
>>> x = Foo[]
>>> for obj in [n, d, x]:
.. print[type[obj] is obj.__class__]
...
True
True
True
5. Ví dụ sau được lấy từ Python 2. 7>>>
>>> class Foo:
.. pass
...
>>> x = Foo[]
>>> x.__class__
>>> type[x]
Lớp học kiểu mới
Các lớp kiểu mới thống nhất các khái niệm về lớp và loại. Nếu
>>> n = 5
>>> d = { 'x' : 1, 'y' : 2 }
>>> class Foo:
.. pass
...
>>> x = Foo[]
>>> for obj in [n, d, x]:
.. print[type[obj] is obj.__class__]
...
True
True
True
6 là một thể hiện của lớp kiểu mới, thì >>> n = 5
>>> d = { 'x' : 1, 'y' : 2 }
>>> class Foo:
.. pass
...
>>> x = Foo[]
>>> for obj in [n, d, x]:
.. print[type[obj] is obj.__class__]
...
True
True
True
8 giống như >>> n = 5
>>> d = { 'x' : 1, 'y' : 2 }
>>> class Foo:
.. pass
...
>>> x = Foo[]
>>> for obj in [n, d, x]:
.. print[type[obj] is obj.__class__]
...
True
True
True
7>>>
>>> class Foo:
.. pass
>>> obj = Foo[]
>>> obj.__class__
>>> type[obj]
>>> obj.__class__ is type[obj]
True
>>>
>>> n = 5
>>> d = { 'x' : 1, 'y' : 2 }
>>> class Foo:
.. pass
...
>>> x = Foo[]
>>> for obj in [n, d, x]:
.. print[type[obj] is obj.__class__]
...
True
True
True
Loại và Lớp
Trong Python 3, tất cả các lớp đều là lớp kiểu mới. Do đó, trong Python 3, thật hợp lý khi đề cập đến loại đối tượng và lớp của nó thay thế cho nhau
Ghi chú. Trong Python 2, các lớp theo mặc định là kiểu cũ. Trước Python 2. 2, các lớp kiểu mới hoàn toàn không được hỗ trợ. Từ Python 2. 2 trở đi, chúng có thể được tạo nhưng phải được khai báo rõ ràng là kiểu mới
Hãy nhớ rằng, trong Python, mọi thứ đều là đối tượng. Lớp cũng là đối tượng. Kết quả là, một lớp phải có một loại. loại của một lớp học là gì?
Hãy xem xét những điều sau đây
>>>
>>> class Foo:
.. pass
...
>>> x = Foo[]
>>> type[x]
>>> type[Foo]
Loại
>>> class Foo:
.. pass
...
>>> x = Foo[]
>>> type[x]
>>> type[Foo]
3 là lớp >>> class Foo:
.. pass
...
>>> x = Foo[]
>>> type[x]
>>> type[Foo]
4, như bạn mong đợi. Nhưng loại >>> class Foo:
.. pass
...
>>> x = Foo[]
>>> type[x]
>>> type[Foo]
4, bản thân lớp, là >>> class Foo:
.. pass
...
>>> x = Foo[]
>>> type[x]
>>> type[Foo]
6. Nói chung, loại của bất kỳ lớp kiểu mới nào là >>> class Foo:
.. pass
...
>>> x = Foo[]
>>> type[x]
>>> type[Foo]
6Loại lớp dựng sẵn mà bạn quen thuộc cũng là
>>> class Foo:
.. pass
...
>>> x = Foo[]
>>> type[x]
>>> type[Foo]
6>>>
>>> for t in int, float, dict, list, tuple:
.. print[type[t]]
...
Đối với vấn đề đó, loại
>>> class Foo:
.. pass
...
>>> x = Foo[]
>>> type[x]
>>> type[Foo]
6 cũng là >>> class Foo:
.. pass
...
>>> x = Foo[]
>>> type[x]
>>> type[Foo]
6 [vâng, thực sự]>>>
>>> type[type]
>>> class Foo:
.. pass
...
>>> x = Foo[]
>>> type[x]
>>> type[Foo]
6 là một siêu dữ liệu, trong đó các lớp là các thể hiện. Giống như một đối tượng bình thường là một thể hiện của một lớp, bất kỳ lớp kiểu mới nào trong Python, và do đó, bất kỳ lớp nào trong Python 3, đều là một thể hiện của siêu dữ liệu >>> class Foo:
.. pass
...
>>> x = Foo[]
>>> type[x]
>>> type[Foo]
6trong trường hợp trên
3 là một thể hiện của lớp>>> class Foo: .. pass ... >>> x = Foo[] >>> type[x] >>> type[Foo]
4>>> class Foo: .. pass ... >>> x = Foo[] >>> type[x] >>> type[Foo]
4 là một thể hiện của siêu dữ liệu>>> class Foo: .. pass ... >>> x = Foo[] >>> type[x] >>> type[Foo]
6>>> class Foo: .. pass ... >>> x = Foo[] >>> type[x] >>> type[Foo]
6 cũng là một thể hiện của siêu dữ liệu>>> class Foo: .. pass ... >>> x = Foo[] >>> type[x] >>> type[Foo]
6, vì vậy nó là một thể hiện của chính nó>>> class Foo: .. pass ... >>> x = Foo[] >>> type[x] >>> type[Foo]
Xác định một lớp động
Hàm
>>> for t in int, float, dict, list, tuple:
.. print[type[t]]
...
9 tích hợp, khi được truyền một đối số, sẽ trả về loại đối tượng. Đối với các lớp kiểu mới, điều đó thường giống như>>>
>>> type[3]
>>> type[['foo', 'bar', 'baz']]
>>> t = [1, 2, 3, 4, 5]
>>> type[t]
>>> class Foo:
.. pass
...
>>> type[Foo[]]
Bạn cũng có thể gọi
>>> for t in int, float, dict, list, tuple:
.. print[type[t]]
...
9 với ba đối số—>>> type[type]
2
3 chỉ định tên lớp. Điều này trở thành thuộc tính>>> type[type]
4 của lớp>>> type[type]
5 chỉ định một bộ các lớp cơ sở mà lớp kế thừa từ đó. Điều này trở thành thuộc tính>>> type[type]
6 của lớp>>> type[type]
7 chỉ định một định nghĩa có chứa nội dung lớp. Điều này trở thành thuộc tính>>> type[type]
8 của lớp>>> type[type]
Gọi
>>> for t in int, float, dict, list, tuple:
.. print[type[t]]
...
9 theo cách này sẽ tạo ra một phiên bản mới của siêu dữ liệu >>> class Foo:
.. pass
...
>>> x = Foo[]
>>> type[x]
>>> type[Foo]
6. Nói cách khác, nó tự động tạo ra một lớp mớiTrong mỗi ví dụ sau đây, đoạn mã trên cùng xác định một lớp linh hoạt với
>>> for t in int, float, dict, list, tuple:
.. print[type[t]]
...
9, trong khi đoạn mã bên dưới xác định lớp theo cách thông thường, với câu lệnh >>> type[3]
>>> type[['foo', 'bar', 'baz']]
>>> t = [1, 2, 3, 4, 5]
>>> type[t]
>>> class Foo:
.. pass
...
>>> type[Foo[]]
2. Trong mỗi trường hợp, hai đoạn mã có chức năng tương đương nhauví dụ 1
Trong ví dụ đầu tiên này, các đối số
>>> type[type]
5 và >>> type[type]
7 được truyền cho >>> for t in int, float, dict, list, tuple:
.. print[type[t]]
...
9 đều trống. Không có kế thừa từ bất kỳ lớp cha nào được chỉ định và ban đầu không có gì được đặt trong từ điển không gian tên. Đây là định nghĩa lớp đơn giản nhất có thể>>>
>>> Foo = type['Foo', [], {}]
>>> x = Foo[]
>>> x
>>>
>>> class Foo:
.. pass
...
>>> x = Foo[]
>>> x
ví dụ 2
Ở đây,
>>> type[type]
5 là một bộ có một phần tử duy nhất là >>> class Foo:
.. pass
...
>>> x = Foo[]
>>> type[x]
>>> type[Foo]
4, chỉ định lớp cha mà >>> type[3]
>>> type[['foo', 'bar', 'baz']]
>>> t = [1, 2, 3, 4, 5]
>>> type[t]
>>> class Foo:
.. pass
...
>>> type[Foo[]]
8 kế thừa từ. Một thuộc tính, >>> type[3]
>>> type[['foo', 'bar', 'baz']]
>>> t = [1, 2, 3, 4, 5]
>>> type[t]
>>> class Foo:
.. pass
...
>>> type[Foo[]]
9, ban đầu được đặt vào từ điển không gian tên>>>
>>> Bar = type['Bar', [Foo,], dict[attr=100]]
>>> x = Bar[]
>>> x.attr
100
>>> x.__class__
>>> x.__class__.__bases__
[,]
>>>
>>> class Foo:
.. pass
>>> obj = Foo[]
>>> obj.__class__
>>> type[obj]
>>> obj.__class__ is type[obj]
True
0ví dụ 3
Lần này,
>>> type[type]
5 lại trống. Hai đối tượng được đặt vào từ điển không gian tên thông qua đối số >>> type[type]
7. Đầu tiên là một thuộc tính có tên là >>> type[3]
>>> type[['foo', 'bar', 'baz']]
>>> t = [1, 2, 3, 4, 5]
>>> type[t]
>>> class Foo:
.. pass
...
>>> type[Foo[]]
9 và hàm thứ hai có tên là >>> Foo = type['Foo', [], {}]
>>> x = Foo[]
>>> x
3, trở thành một phương thức của lớp đã xác định>>>
>>> class Foo:
.. pass
>>> obj = Foo[]
>>> obj.__class__
>>> type[obj]
>>> obj.__class__ is type[obj]
True
1>>>
>>> class Foo:
.. pass
>>> obj = Foo[]
>>> obj.__class__
>>> type[obj]
>>> obj.__class__ is type[obj]
True
2Ví dụ 4
Chỉ có thể định nghĩa các hàm rất đơn giản bằng
>>> Foo = type['Foo', [], {}]
>>> x = Foo[]
>>> x
4 trong Python. Trong ví dụ sau, một hàm phức tạp hơn một chút được định nghĩa bên ngoài, sau đó được gán cho >>> Foo = type['Foo', [], {}]
>>> x = Foo[]
>>> x
3 trong từ điển không gian tên thông qua tên >>> Foo = type['Foo', [], {}]
>>> x = Foo[]
>>> x
6>>> ____9_______3
>>>
>>> class Foo:
.. pass
>>> obj = Foo[]
>>> obj.__class__
>>> type[obj]
>>> obj.__class__ is type[obj]
True
4Siêu dữ liệu tùy chỉnh
Hãy xem xét lại ví dụ quen thuộc này
>>> ____9_______5
Biểu thức
>>> Foo = type['Foo', [], {}]
>>> x = Foo[]
>>> x
7 tạo một thể hiện mới của lớp >>> class Foo:
.. pass
...
>>> x = Foo[]
>>> type[x]
>>> type[Foo]
4. Khi thông dịch viên gặp >>> Foo = type['Foo', [], {}]
>>> x = Foo[]
>>> x
7, điều sau xảy raPhương thức
0 của lớp cha của>>> class Foo: .. pass ... >>> x = Foo[] >>> x
4 được gọi là. Vì>>> class Foo: .. pass ... >>> x = Foo[] >>> type[x] >>> type[Foo]
4 là một lớp kiểu mới tiêu chuẩn, nên lớp cha của nó là siêu dữ liệu>>> class Foo: .. pass ... >>> x = Foo[] >>> type[x] >>> type[Foo]
6, vì vậy phương thức>>> class Foo: .. pass ... >>> x = Foo[] >>> type[x] >>> type[Foo]
0 của>>> class Foo: .. pass ... >>> x = Foo[] >>> x
6 được gọi>>> class Foo: .. pass ... >>> x = Foo[] >>> type[x] >>> type[Foo]
Phương thức
0 đó lần lượt gọi như sau>>> class Foo: .. pass ... >>> x = Foo[] >>> x
7>>> class Foo: .. pass ... >>> x = Foo[] >>> x
8>>> class Foo: .. pass ... >>> x = Foo[] >>> x
Nếu
>>> class Foo:
.. pass
...
>>> x = Foo[]
>>> type[x]
>>> type[Foo]
4 không xác định >>> class Foo:
.. pass
...
>>> x = Foo[]
>>> x
7 và >>> class Foo:
.. pass
...
>>> x = Foo[]
>>> x
8, các phương thức mặc định được kế thừa từ tổ tiên của >>> class Foo:
.. pass
...
>>> x = Foo[]
>>> type[x]
>>> type[Foo]
4. Nhưng nếu >>> class Foo:
.. pass
...
>>> x = Foo[]
>>> type[x]
>>> type[Foo]
4 xác định các phương thức này, thì chúng sẽ ghi đè lên các phương thức từ tổ tiên, điều này cho phép hành vi tùy chỉnh khi khởi tạo >>> class Foo:
.. pass
...
>>> x = Foo[]
>>> type[x]
>>> type[Foo]
4Trong phần sau đây, một phương thức tùy chỉnh có tên là
>>> Bar = type['Bar', [Foo,], dict[attr=100]]
>>> x = Bar[]
>>> x.attr
100
>>> x.__class__
>>> x.__class__.__bases__
[,]
5 được định nghĩa và chỉ định làm phương thức >>> class Foo:
.. pass
...
>>> x = Foo[]
>>> x
7 cho >>> class Foo:
.. pass
...
>>> x = Foo[]
>>> type[x]
>>> type[Foo]
4>>>
>>> class Foo:
.. pass
>>> obj = Foo[]
>>> obj.__class__
>>> type[obj]
>>> obj.__class__ is type[obj]
True
6Điều này sửa đổi hành vi khởi tạo của lớp
>>> class Foo:
.. pass
...
>>> x = Foo[]
>>> type[x]
>>> type[Foo]
4. mỗi khi một thể hiện của >>> class Foo:
.. pass
...
>>> x = Foo[]
>>> type[x]
>>> type[Foo]
4 được tạo, theo mặc định, nó được khởi tạo với một thuộc tính có tên là >>> type[3]
>>> type[['foo', 'bar', 'baz']]
>>> t = [1, 2, 3, 4, 5]
>>> type[t]
>>> class Foo:
.. pass
...
>>> type[Foo[]]
9, có giá trị là >>> class Foo:
.. pass
>>> obj = Foo[]
>>> obj.__class__
>>> type[obj]
>>> obj.__class__ is type[obj]
True
01. [Mã như thế này thường xuất hiện trong phương thức >>> class Foo:
.. pass
...
>>> x = Foo[]
>>> x
8 và không thường xuất hiện trong phương thức >>> class Foo:
.. pass
...
>>> x = Foo[]
>>> x
7. Ví dụ này được tạo ra cho mục đích trình diễn. ]Bây giờ, như đã được nhắc lại, lớp cũng là đối tượng. Giả sử bạn muốn tùy chỉnh tương tự hành vi khởi tạo khi tạo một lớp như
>>> class Foo:
.. pass
...
>>> x = Foo[]
>>> type[x]
>>> type[Foo]
4. Nếu bạn làm theo mẫu ở trên, bạn sẽ xác định lại một phương thức tùy chỉnh và gán nó làm phương thức >>> class Foo:
.. pass
...
>>> x = Foo[]
>>> x
7 cho lớp mà >>> class Foo:
.. pass
...
>>> x = Foo[]
>>> type[x]
>>> type[Foo]
4 là một thể hiện. >>> class Foo:
.. pass
...
>>> x = Foo[]
>>> type[x]
>>> type[Foo]
4 là một thể hiện của siêu dữ liệu >>> class Foo:
.. pass
...
>>> x = Foo[]
>>> type[x]
>>> type[Foo]
6, vì vậy mã trông giống như thế này>>>
>>> class Foo:
.. pass
>>> obj = Foo[]
>>> obj.__class__
>>> type[obj]
>>> obj.__class__ is type[obj]
True
7Ngoại trừ, như bạn có thể thấy, bạn không thể chỉ định lại phương thức
>>> class Foo:
.. pass
...
>>> x = Foo[]
>>> x
7 của siêu dữ liệu >>> class Foo:
.. pass
...
>>> x = Foo[]
>>> type[x]
>>> type[Foo]
6. Python không cho phép nóĐiều này có lẽ cũng tốt.
>>> class Foo:
.. pass
...
>>> x = Foo[]
>>> type[x]
>>> type[Foo]
6 là siêu dữ liệu mà từ đó tất cả các lớp kiểu mới được bắt nguồn. Dù sao thì bạn thực sự không nên loay hoay với nó. Nhưng sau đó, có cách nào để truy vấn, nếu bạn muốn tùy chỉnh việc khởi tạo một lớp?Một giải pháp khả thi là siêu dữ liệu tùy chỉnh. Về cơ bản, thay vì loay hoay với siêu dữ liệu
>>> class Foo:
.. pass
...
>>> x = Foo[]
>>> type[x]
>>> type[Foo]
6, bạn có thể xác định siêu dữ liệu của riêng mình, bắt nguồn từ >>> class Foo:
.. pass
...
>>> x = Foo[]
>>> type[x]
>>> type[Foo]
6, và sau đó bạn có thể sử dụng siêu dữ liệu đó để thay thếBước đầu tiên là xác định siêu dữ liệu bắt nguồn từ
>>> class Foo:
.. pass
...
>>> x = Foo[]
>>> type[x]
>>> type[Foo]
6, như sau>>>
>>> class Foo:
.. pass
>>> obj = Foo[]
>>> obj.__class__
>>> type[obj]
>>> obj.__class__ is type[obj]
True
8Tiêu đề định nghĩa
>>> class Foo:
.. pass
>>> obj = Foo[]
>>> obj.__class__
>>> type[obj]
>>> obj.__class__ is type[obj]
True
15 xác định rằng >>> class Foo:
.. pass
>>> obj = Foo[]
>>> obj.__class__
>>> type[obj]
>>> obj.__class__ is type[obj]
True
16 bắt nguồn từ >>> class Foo:
.. pass
...
>>> x = Foo[]
>>> type[x]
>>> type[Foo]
6. Vì >>> class Foo:
.. pass
...
>>> x = Foo[]
>>> type[x]
>>> type[Foo]
6 là một siêu dữ liệu, điều đó làm cho >>> class Foo:
.. pass
>>> obj = Foo[]
>>> obj.__class__
>>> type[obj]
>>> obj.__class__ is type[obj]
True
16 cũng là một siêu dữ liệuLưu ý rằng một phương pháp
>>> class Foo:
.. pass
...
>>> x = Foo[]
>>> x
7 tùy chỉnh đã được xác định cho >>> class Foo:
.. pass
>>> obj = Foo[]
>>> obj.__class__
>>> type[obj]
>>> obj.__class__ is type[obj]
True
16. Không thể làm điều đó trực tiếp với siêu dữ liệu >>> class Foo:
.. pass
...
>>> x = Foo[]
>>> type[x]
>>> type[Foo]
6. Phương pháp >>> class Foo:
.. pass
...
>>> x = Foo[]
>>> x
7 thực hiện như sau- Ủy quyền thông qua
24 cho phương thức>>> class Foo: .. pass >>> obj = Foo[] >>> obj.__class__ >>> type[obj] >>> obj.__class__ is type[obj] True
7 của siêu dữ liệu gốc [>>> class Foo: .. pass ... >>> x = Foo[] >>> x
6] để thực sự tạo một lớp mới>>> class Foo: .. pass ... >>> x = Foo[] >>> type[x] >>> type[Foo]
- Gán thuộc tính tùy chỉnh
9 cho lớp, với giá trị là>>> type[3] >>> type[['foo', 'bar', 'baz']] >>> t = [1, 2, 3, 4, 5] >>> type[t] >>> class Foo: .. pass ... >>> type[Foo[]]
01>>> class Foo: .. pass >>> obj = Foo[] >>> obj.__class__ >>> type[obj] >>> obj.__class__ is type[obj] True
- Trả về lớp vừa tạo
Bây giờ nửa còn lại của voodoo. Xác định một lớp mới
>>> class Foo:
.. pass
...
>>> x = Foo[]
>>> type[x]
>>> type[Foo]
4 và chỉ định rằng siêu dữ liệu của nó là siêu dữ liệu tùy chỉnh >>> class Foo:
.. pass
>>> obj = Foo[]
>>> obj.__class__
>>> type[obj]
>>> obj.__class__ is type[obj]
True
16, chứ không phải là siêu dữ liệu tiêu chuẩn >>> class Foo:
.. pass
...
>>> x = Foo[]
>>> type[x]
>>> type[Foo]
6. Điều này được thực hiện bằng cách sử dụng từ khóa >>> class Foo:
.. pass
>>> obj = Foo[]
>>> obj.__class__
>>> type[obj]
>>> obj.__class__ is type[obj]
True
32 trong định nghĩa lớp như sau>>>
>>> class Foo:
.. pass
>>> obj = Foo[]
>>> obj.__class__
>>> type[obj]
>>> obj.__class__ is type[obj]
True
9thì đấy.
>>> class Foo:
.. pass
...
>>> x = Foo[]
>>> type[x]
>>> type[Foo]
4 đã tự động chọn thuộc tính >>> type[3]
>>> type[['foo', 'bar', 'baz']]
>>> t = [1, 2, 3, 4, 5]
>>> type[t]
>>> class Foo:
.. pass
...
>>> type[Foo[]]
9 từ siêu dữ liệu >>> class Foo:
.. pass
>>> obj = Foo[]
>>> obj.__class__
>>> type[obj]
>>> obj.__class__ is type[obj]
True
16. Tất nhiên, bất kỳ lớp nào khác mà bạn định nghĩa tương tự cũng sẽ làm như vậy>>>
>>> n = 5
>>> d = { 'x' : 1, 'y' : 2 }
>>> class Foo:
.. pass
...
>>> x = Foo[]
>>> for obj in [n, d, x]:
.. print[type[obj] is obj.__class__]
...
True
True
True
0Cũng giống như cách mà một lớp có chức năng như một khuôn mẫu để tạo ra các đối tượng, một siêu lớp có chức năng như một khuôn mẫu để tạo ra các lớp. Siêu lớp đôi khi được gọi là nhà máy lớp
So sánh hai ví dụ sau
nhà máy đối tượng
>>>
>>> n = 5
>>> d = { 'x' : 1, 'y' : 2 }
>>> class Foo:
.. pass
...
>>> x = Foo[]
>>> for obj in [n, d, x]:
.. print[type[obj] is obj.__class__]
...
True
True
True
1lớp nhà máy
>>>
>>> n = 5
>>> d = { 'x' : 1, 'y' : 2 }
>>> class Foo:
.. pass
...
>>> x = Foo[]
>>> for obj in [n, d, x]:
.. print[type[obj] is obj.__class__]
...
True
True
True
2Loại bỏ các quảng cáoĐiều này có thực sự cần thiết?
Đơn giản như ví dụ về nhà máy lớp ở trên, đó là bản chất của cách hoạt động của siêu dữ liệu. Chúng cho phép tùy chỉnh khởi tạo lớp
Tuy nhiên, việc cấp thuộc tính tùy chỉnh
>>> type[3]
>>> type[['foo', 'bar', 'baz']]
>>> t = [1, 2, 3, 4, 5]
>>> type[t]
>>> class Foo:
.. pass
...
>>> type[Foo[]]
9 cho mỗi lớp mới tạo đã gây ra rất nhiều phiền phức. Bạn có thực sự cần một siêu dữ liệu chỉ cho điều đó?Trong Python, có ít nhất một số cách khác để thực hiện điều tương tự một cách hiệu quả
Kế thừa đơn giản
>>>
>>> n = 5
>>> d = { 'x' : 1, 'y' : 2 }
>>> class Foo:
.. pass
...
>>> x = Foo[]
>>> for obj in [n, d, x]:
.. print[type[obj] is obj.__class__]
...
True
True
True
3trang trí lớp học
>>>
>>> n = 5
>>> d = { 'x' : 1, 'y' : 2 }
>>> class Foo:
.. pass
...
>>> x = Foo[]
>>> for obj in [n, d, x]:
.. print[type[obj] is obj.__class__]
...
True
True
True
4Phần kết luận
Như Tim Peters gợi ý, siêu dữ liệu có thể dễ dàng biến thành một “giải pháp để tìm kiếm một vấn đề. ” Thường không cần thiết phải tạo các siêu dữ liệu tùy chỉnh. Nếu vấn đề hiện tại có thể được giải quyết theo cách đơn giản hơn, thì có lẽ nên. Tuy nhiên, sẽ rất hữu ích khi hiểu siêu dữ liệu để bạn hiểu các lớp Python nói chung và có thể nhận ra khi nào siêu dữ liệu thực sự là công cụ thích hợp để sử dụng
Đánh dấu là đã hoàn thành
🐍 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
Gửi cho tôi thủ thuật Python »
Giới thiệu về John Sturtz
John là một Pythonista cuồng nhiệt và là thành viên của nhóm hướng dẫn Real Python
» Thông tin thêm về JohnMỗ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à
Aldren
Đan
Joanna
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 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 »
Chuyên gia 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ẻ EmailBà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. 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