Python tạo kiểu lớp

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)

Tự mình thử »

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


Python tạo kiểu lớp


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()

Tự mình thử »

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()

Tự mình thử »


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áo

Lớ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)

6

Loạ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)

6

trong trường hợp trên

  • >>> class Foo:
    ..     pass
    ...
    >>> x = Foo()
    
    >>> type(x)
    
    
    >>> type(Foo)
    
    
    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ó
Python tạo kiểu lớp

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

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

  • >>> type(type)
    
    
    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

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ới

Trong 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 nhau

ví 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
<__main__.Foo object at 0x04CFAD50>

>>>

>>> class Foo:
..     pass
...
>>> x = Foo()
>>> x
<__main__.Foo object at 0x0370AD50>

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
0

ví 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
<__main__.Foo object at 0x04CFAD50>
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
2

Ví 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
<__main__.Foo object at 0x04CFAD50>
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
<__main__.Foo object at 0x04CFAD50>
3 trong từ điển không gian tên thông qua tên
>>> Foo = type('Foo', (), {})

>>> x = Foo()
>>> x
<__main__.Foo object at 0x04CFAD50>
6

>>> ____9_______3

>>>

>>> class Foo:
..     pass
>>> obj = Foo()
>>> obj.__class__

>>> type(obj)

>>> obj.__class__ is type(obj)
True
4

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

Siê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
<__main__.Foo object at 0x04CFAD50>
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
<__main__.Foo object at 0x04CFAD50>
7, điều sau xảy ra

  • Phương thức

    >>> class Foo:
    ..     pass
    ...
    >>> x = Foo()
    >>> x
    <__main__.Foo object at 0x0370AD50>
    
    0 của lớp cha của
    >>> class Foo:
    ..     pass
    ...
    >>> x = Foo()
    
    >>> type(x)
    
    
    >>> type(Foo)
    
    
    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()
    >>> x
    <__main__.Foo object at 0x0370AD50>
    
    0 của
    >>> class Foo:
    ..     pass
    ...
    >>> x = Foo()
    
    >>> type(x)
    
    
    >>> type(Foo)
    
    
    6 được gọi

  • Phương thức

    >>> class Foo:
    ..     pass
    ...
    >>> x = Foo()
    >>> x
    <__main__.Foo object at 0x0370AD50>
    
    0 đó lần lượt gọi như sau

    • >>> class Foo:
      ..     pass
      ...
      >>> x = Foo()
      >>> x
      <__main__.Foo object at 0x0370AD50>
      
      7
    • >>> class Foo:
      ..     pass
      ...
      >>> x = Foo()
      >>> x
      <__main__.Foo object at 0x0370AD50>
      
      8

Nếu

>>> class Foo:
..     pass
...
>>> x = Foo()

>>> type(x)


>>> type(Foo)

4 không xác định
>>> class Foo:
..     pass
...
>>> x = Foo()
>>> x
<__main__.Foo object at 0x0370AD50>
7 và
>>> class Foo:
..     pass
...
>>> x = Foo()
>>> x
<__main__.Foo object at 0x0370AD50>
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)

4

Trong 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
<__main__.Foo object at 0x0370AD50>
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
<__main__.Foo object at 0x0370AD50>
8 và không thường xuất hiện trong phương thức
>>> class Foo:
..     pass
...
>>> x = Foo()
>>> x
<__main__.Foo object at 0x0370AD50>
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
<__main__.Foo object at 0x0370AD50>
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
7

Ngoạ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
<__main__.Foo object at 0x0370AD50>
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
8

Tiê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ệu

Lưu ý rằng một phương pháp

>>> class Foo:
..     pass
...
>>> x = Foo()
>>> x
<__main__.Foo object at 0x0370AD50>
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
<__main__.Foo object at 0x0370AD50>
7 thực hiện như sau

  • Ủy quyền thông qua
    >>> class Foo:
    ..     pass
    >>> obj = Foo()
    >>> obj.__class__
    
    >>> type(obj)
    
    >>> obj.__class__ is type(obj)
    True
    
    24 cho phương thức
    >>> class Foo:
    ..     pass
    ...
    >>> x = Foo()
    >>> x
    <__main__.Foo object at 0x0370AD50>
    
    7 của siêu dữ liệu gốc (
    >>> class Foo:
    ..     pass
    ...
    >>> x = Foo()
    
    >>> type(x)
    
    
    >>> type(Foo)
    
    
    6) để thực sự tạo một lớp mới
  • Gán 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 lớp, với giá trị là
    >>> class Foo:
    ..     pass
    >>> obj = Foo()
    >>> obj.__class__
    
    >>> type(obj)
    
    >>> obj.__class__ is type(obj)
    True
    
    01
  • 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
9

thì đấ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
0

Cũ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
1

lớ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
2

Loạ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
3

trang 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
4

Phầ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

Python tạo kiểu lớp

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

Giới thiệu về John Sturtz

Python tạo kiểu lớp
Python tạo kiểu lớp

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ề John


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à

Python tạo kiểu lớp

Aldren

Python tạo kiểu lớp

Đan

Python tạo kiểu lớp

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ẻ 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. 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ể tạo một kiểu trong Python không?

Câu trả lời ngắn gọn là bạn không thể tạo một loại mới trong python mà không chỉnh sửa mã nguồn (được viết bằng C). Tuy nhiên, câu trả lời về việc tạo một lớp trong python có lẽ là cách dễ dàng hơn vì việc chỉnh sửa nguồn có thể tạo ra các vấn đề tương thích với các gói (có thể nói).

Loại lớp trong Python là gì?

loại là siêu dữ liệu, trong đó các lớp là các thể hiện . Giống như một đối tượng thông 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 kiểu. trong trường hợp trên. x là một thể hiện của lớp Foo. Foo là một thể hiện của loại siêu dữ liệu.

Kiểu () trong Python là gì?

Cú pháp hàm type() trong Python . Cú pháp hàm kiểu Python () là. type(object) type(name, base, dict) Khi một đối số duy nhất được truyền cho hàm type(), nó sẽ trả về kiểu của đối tượng. Giá trị của nó giống như đối tượng. used to get the type of an object. Python type() function syntax is: type(object) type(name, bases, dict) When a single argument is passed to the type() function, it returns the type of the object. Its value is the same as the object.

Việc tạo một lớp mới có tạo ra một loại mới không?

Tạo một lớp mới sẽ tạo ra một loại đối tượng mới , cho phép tạo các phiên bản mới của loại đó. Mỗi thể hiện của lớp có thể có các thuộc tính gắn liền với nó để duy trì trạng thái của nó. Các thể hiện của lớp cũng có thể có các phương thức (được định nghĩa bởi lớp của nó) để sửa đổi trạng thái của nó.