Tuyên bố đúng về lớp python

Python là một ngôn ngữ lập trình hướng đối tượng, có nghĩa là nó cung cấp các tính năng hỗ trợ lập trình hướng đối tượng (OOP)

Lập trình hướng đối tượng bắt nguồn từ những năm 1960, nhưng mãi đến giữa những năm 1980, nó mới trở thành mô hình lập trình chính được sử dụng để tạo ra phần mềm mới. Nó được phát triển như một cách để xử lý quy mô và độ phức tạp ngày càng tăng nhanh chóng của các hệ thống phần mềm và giúp dễ dàng sửa đổi các hệ thống lớn và phức tạp này theo thời gian

Cho đến bây giờ, chúng tôi đã viết chương trình bằng cách sử dụng mô hình lập trình thủ tục. Trong lập trình thủ tục, trọng tâm là viết các hàm hoặc thủ tục hoạt động trên dữ liệu. Trong lập trình hướng đối tượng, trọng tâm là tạo ra các đối tượng chứa cả dữ liệu và chức năng cùng nhau

7. 2. Các loại kết hợp do người dùng định nghĩa¶

Bây giờ chúng ta sẽ giới thiệu một từ khóa Python mới, class, về bản chất nó định nghĩa một kiểu dữ liệu mới. Chúng tôi đã sử dụng một số loại tích hợp sẵn của Python trong suốt cuốn sách này, giờ đây chúng tôi đã sẵn sàng để tạo loại do người dùng xác định của riêng mình.

print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
5

Xét khái niệm điểm toán học. Trong hai chiều, một điểm là hai số (tọa độ) được coi như một đối tượng duy nhất. Trong ký hiệu toán học, điểm thường được viết trong ngoặc đơn với dấu phẩy ngăn cách tọa độ. Ví dụ:

print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
6 đại diện cho gốc tọa độ và
print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
7 đại diện cho điểm
print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
8 đơn vị ở bên phải và
print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
9 đơn vị phía trên so với gốc tọa độ

Một cách tự nhiên để biểu thị một điểm trong Python là có hai giá trị số. Sau đó, câu hỏi đặt ra là làm thế nào để nhóm hai giá trị này thành một đối tượng phức hợp. Giải pháp nhanh và bẩn là sử dụng danh sách hoặc bộ dữ liệu và đối với một số ứng dụng, đây có thể là lựa chọn tốt nhất

Một cách khác là định nghĩa một loại hợp chất mới do người dùng định nghĩa, được gọi là một lớp. Cách tiếp cận này đòi hỏi nhiều nỗ lực hơn một chút, nhưng nó có những ưu điểm sẽ sớm xuất hiện

Một định nghĩa lớp trông như thế này

class Point:
    pass

Các định nghĩa lớp có thể xuất hiện ở bất kỳ đâu trong chương trình, nhưng chúng thường ở gần phần đầu (sau các câu lệnh

>>> p2 = Point()
>>> p2.x
Traceback (most recent call last):
  File "", line 1, in 
AttributeError: 'Point' object has no attribute 'x'
>>>
0). Các quy tắc cú pháp cho một định nghĩa lớp cũng giống như đối với các câu lệnh ghép khác. Có một tiêu đề bắt đầu bằng từ khóa,
>>> p2 = Point()
>>> p2.x
Traceback (most recent call last):
  File "", line 1, in 
AttributeError: 'Point' object has no attribute 'x'
>>>
1, theo sau là tên của lớp và kết thúc bằng dấu hai chấm

Định nghĩa này tạo ra một lớp mới gọi là

print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
5. Câu lệnh vượt qua không có hiệu lực; . Một chuỗi tài liệu có thể phục vụ cùng một mục đích

class Point:
    "Point class for storing mathematical points."

Bằng cách tạo lớp

print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
5, chúng tôi đã tạo một loại mới, còn được gọi là
print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
5. Các thành viên của loại này được gọi là thể hiện của loại hoặc đối tượng. Việc tạo một thể hiện mới được gọi là khởi tạo và được thực hiện bằng cách gọi lớp. Các lớp, giống như các hàm, có thể gọi được và chúng ta khởi tạo một đối tượng
print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
5 bằng cách gọi lớp
print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
5

print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
4

Biến

>>> p2 = Point()
>>> p2.x
Traceback (most recent call last):
  File "", line 1, in 
AttributeError: 'Point' object has no attribute 'x'
>>>
7 được gán một tham chiếu đến một đối tượng
print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
5 mới

Có thể hữu ích khi nghĩ về một lớp như một nhà máy để tạo ra các đối tượng, vì vậy lớp

print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
5 của chúng ta là một nhà máy để tạo ra các điểm. Bản thân lớp không phải là một thể hiện của một điểm, nhưng nó chứa bộ máy để tạo ra các thể hiện của điểm

7. 3. Thuộc tính¶

Giống như các đối tượng trong thế giới thực, các thể hiện đối tượng có cả hình thức và chức năng. Biểu mẫu bao gồm các thành phần dữ liệu chứa trong thể hiện

Chúng ta có thể thêm các phần tử dữ liệu mới vào một thể hiện bằng cách sử dụng ký hiệu dấu chấm

print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
8

Cú pháp này tương tự như cú pháp để chọn một biến từ một mô-đun, chẳng hạn như

print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
90 hoặc
print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
91. Cả mô-đun và phiên bản đều tạo không gian tên riêng của chúng và cú pháp để truy cập tên có trong mỗi, được gọi là thuộc tính, là giống nhau. Trong trường hợp này, thuộc tính chúng tôi đang chọn là một mục dữ liệu từ một thể hiện

Sơ đồ trạng thái sau đây cho thấy kết quả của các nhiệm vụ này

Tuyên bố đúng về lớp python

Biến

>>> p2 = Point()
>>> p2.x
Traceback (most recent call last):
  File "", line 1, in 
AttributeError: 'Point' object has no attribute 'x'
>>>
7 đề cập đến một đối tượng Điểm, chứa hai thuộc tính. Mỗi thuộc tính đề cập đến một số

Chúng ta có thể đọc giá trị của một thuộc tính bằng cùng một cú pháp

print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
2

Biểu thức

print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
93 có nghĩa là, “Đi tới đối tượng mà
>>> p2 = Point()
>>> p2.x
Traceback (most recent call last):
  File "", line 1, in 
AttributeError: 'Point' object has no attribute 'x'
>>>
7 đề cập đến và nhận giá trị của
print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
8”. Trong trường hợp này, chúng ta gán giá trị đó cho một biến có tên là
print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
8. Không có xung đột giữa biến
print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
8 và thuộc tính
print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
8. Mục đích của ký hiệu dấu chấm là để xác định rõ ràng bạn đang đề cập đến biến nào

Bạn có thể sử dụng ký hiệu dấu chấm như một phần của bất kỳ biểu thức nào, vì vậy các câu sau đây là hợp pháp

print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y

Dòng đầu tiên xuất ra

print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
99;

7. 4. Phương thức khởi tạo và print('({0}, {1})'.format(p.x, p.y)) distance_squared = p.x * p.x + p.y * p.y 10¶

Vì lớp

print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
5 của chúng tôi nhằm mục đích biểu diễn các điểm toán học hai chiều, nên tất cả các thể hiện điểm phải có các thuộc tính
print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
8 và
print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
9, nhưng điều đó vẫn chưa đúng với các đối tượng
print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
5 của chúng tôi

>>> p2 = Point()
>>> p2.x
Traceback (most recent call last):
  File "", line 1, in 
AttributeError: 'Point' object has no attribute 'x'
>>>

Để giải quyết vấn đề này, chúng tôi thêm một phương thức khởi tạo vào lớp của chúng tôi

print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
9

Một phương thức hoạt động giống như một hàm nhưng nó là một phần của đối tượng. Giống như một thuộc tính dữ liệu, nó được truy cập bằng ký hiệu dấu chấm

Phương thức khởi tạo là một phương thức đặc biệt được gọi tự động khi một đối tượng được tạo bằng cách gọi lớp. Tên của phương thức này là

print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
15 (hai ký tự gạch dưới, tiếp theo là
print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
16, và sau đó là hai dấu gạch dưới nữa). Tên này phải được sử dụng để biến một phương thức thành phương thức khởi tạo trong Python

Không có xung đột giữa thuộc tính

print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
17 và tham số
print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
8. Ký hiệu dấu chấm chỉ định biến nào chúng ta đang đề cập đến

Hãy thêm một phương thức khác,

print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
19, để hiểu rõ hơn cách thức hoạt động của các phương thức

print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
1

Hãy tạo một vài trường hợp điểm, xem xét các thuộc tính của chúng và gọi phương thức mới của chúng ta trên chúng

print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
4

Khi xác định một phương thức, tham số đầu tiên đề cập đến thể hiện được tạo. Theo thông lệ, tự đặt tên cho tham số này. Trong phiên ví dụ ở trên, tham số

print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
10 đề cập đến các phiên bản
>>> p2 = Point()
>>> p2.x
Traceback (most recent call last):
  File "", line 1, in 
AttributeError: 'Point' object has no attribute 'x'
>>>
7,
print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
42 và
print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
43 tương ứng

7. 5. Các trường hợp dưới dạng tham số¶

Bạn có thể truyền một thể hiện dưới dạng tham số cho hàm theo cách thông thường. Ví dụ

class Point:
    "Point class for storing mathematical points."
0

print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
44 lấy một điểm làm đối số và hiển thị nó ở định dạng chuẩn. Nếu bạn gọi
print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
45 với điểm
>>> p2 = Point()
>>> p2.x
Traceback (most recent call last):
  File "", line 1, in 
AttributeError: 'Point' object has no attribute 'x'
>>>
7 như đã định nghĩa trước đó, đầu ra là
print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
99

Để chuyển đổi

print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
44 thành một phương thức, hãy làm như sau

  1. Thụt lề định nghĩa hàm để nó nằm trong định nghĩa lớp

  2. Đổi tên tham số thành

    print('({0}, {1})'.format(p.x, p.y))
    distance_squared = p.x * p.x + p.y * p.y
    
    10

class Point:
    "Point class for storing mathematical points."
1

Bây giờ chúng ta có thể gọi phương thức bằng ký hiệu dấu chấm

class Point:
    "Point class for storing mathematical points."
2

Đối tượng mà phương thức được gọi được gán cho tham số đầu tiên, vì vậy trong trường hợp này,

>>> p2 = Point()
>>> p2.x
Traceback (most recent call last):
  File "", line 1, in 
AttributeError: 'Point' object has no attribute 'x'
>>>
7 được gán cho tham số
print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
10. Theo quy ước, tham số đầu tiên của một phương thức được gọi là
print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
10. Lý do cho điều này hơi phức tạp, nhưng nó dựa trên một phép ẩn dụ hữu ích

Cú pháp gọi hàm,

print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
45, gợi ý rằng hàm là tác nhân tích cực. Nó nói đại loại như, Này
print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
44. Đây là một đối tượng để bạn in

Trong lập trình hướng đối tượng, các đối tượng là tác nhân tích cực. Một lời gọi như

class Point:
    "Point class for storing mathematical points."
05 nói Hey
>>> p2 = Point()
>>> p2.x
Traceback (most recent call last):
  File "", line 1, in 
AttributeError: 'Point' object has no attribute 'x'
>>>
7. Hãy in cho mình

Sự thay đổi quan điểm này có thể lịch sự hơn, nhưng không rõ ràng là nó hữu ích. Trong các ví dụ chúng ta đã thấy cho đến nay, nó có thể không. Nhưng đôi khi việc chuyển trách nhiệm từ các chức năng sang các đối tượng giúp viết các chức năng linh hoạt hơn và giúp duy trì và sử dụng lại mã dễ dàng hơn

7. 6. Các tính năng hướng đối tượng¶

Không dễ để định nghĩa lập trình hướng đối tượng, nhưng chúng ta đã thấy một số đặc điểm của nó

  1. Các chương trình được tạo thành từ các định nghĩa lớp chứa các thuộc tính có thể là dữ liệu (biến thể hiện) hoặc hành vi (phương thức)

  2. Mỗi định nghĩa đối tượng tương ứng với một số đối tượng hoặc khái niệm trong thế giới thực và các chức năng hoạt động trên đối tượng đó tương ứng với cách các đối tượng trong thế giới thực tương tác

  3. Hầu hết các tính toán được thể hiện dưới dạng các hoạt động trên các đối tượng

Ví dụ, lớp

print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
5 tương ứng với khái niệm toán học của một điểm

7. 7. Thời gian¶

Như một ví dụ khác về loại do người dùng định nghĩa, chúng tôi sẽ định nghĩa một lớp có tên là

class Point:
    "Point class for storing mathematical points."
08 ghi lại thời gian trong ngày. Vì thời gian sẽ cần các thuộc tính giờ, phút và giây, nên chúng ta sẽ bắt đầu với một phương thức khởi tạo tương tự như phương thức chúng ta đã tạo cho Điểm

Định nghĩa lớp trông như thế này

class Point:
    "Point class for storing mathematical points."
3

Khi chúng tôi gọi lớp

class Point:
    "Point class for storing mathematical points."
08, các đối số mà chúng tôi cung cấp sẽ được chuyển đến lớp
print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
16

class Point:
    "Point class for storing mathematical points."
4

Đây là một phương thức

class Point:
    "Point class for storing mathematical points."
11 cho các đối tượng
class Point:
    "Point class for storing mathematical points."
08 của chúng tôi sử dụng định dạng chuỗi để hiển thị phút và giây với hai chữ số

Để tiết kiệm dung lượng, chúng tôi sẽ bỏ qua phương thức khởi tạo, nhưng bạn nên đưa nó vào

class Point:
    "Point class for storing mathematical points."
5

mà bây giờ chúng ta có thể gọi các trường hợp thời gian theo cách thông thường

class Point:
    "Point class for storing mathematical points."
6

7. 8. Đối số tùy chọn¶

Chúng ta đã thấy các hàm tích hợp có số lượng đối số thay đổi. Ví dụ:

class Point:
    "Point class for storing mathematical points."
13 có thể nhận hai, ba hoặc bốn đối số

Có thể viết các hàm do người dùng định nghĩa với danh sách đối số tùy chọn. Ví dụ: chúng tôi có thể nâng cấp phiên bản

class Point:
    "Point class for storing mathematical points."
14 của riêng mình để làm điều tương tự như
class Point:
    "Point class for storing mathematical points."
13

Đây là phiên bản gốc

class Point:
    "Point class for storing mathematical points."
7

Đây là phiên bản mới và cải tiến

class Point:
    "Point class for storing mathematical points."
8

Tham số thứ ba,

class Point:
    "Point class for storing mathematical points."
16, là tùy chọn vì giá trị mặc định,
class Point:
    "Point class for storing mathematical points."
17, được cung cấp. Nếu chúng ta gọi
class Point:
    "Point class for storing mathematical points."
14 chỉ với hai đối số, chúng ta sẽ sử dụng giá trị mặc định và bắt đầu từ đầu chuỗi

class Point:
    "Point class for storing mathematical points."
9

Nếu chúng tôi cung cấp tham số thứ ba, tham số này sẽ ghi đè tham số mặc định

print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
40

Chúng ta có thể viết lại phương thức khởi tạo của mình cho lớp

class Point:
    "Point class for storing mathematical points."
08 sao cho mỗi đối số tùy chọn là
class Point:
    "Point class for storing mathematical points."
20,
class Point:
    "Point class for storing mathematical points."
21 và
class Point:
    "Point class for storing mathematical points."
22

print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
41

Khi chúng ta khởi tạo một đối tượng

class Point:
    "Point class for storing mathematical points."
08, chúng ta có thể chuyển các giá trị cho ba tham số, như chúng ta đã làm với

print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
42

Tuy nhiên, vì các tham số hiện là tùy chọn nên chúng ta có thể bỏ qua chúng

print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
43

Hoặc chỉ cung cấp tham số đầu tiên

print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
44

Hoặc hai tham số đầu tiên

print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
45

Cuối cùng, chúng ta có thể cung cấp một tập hợp con các tham số bằng cách đặt tên rõ ràng cho chúng

print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
46

7. 9. Phương pháp khác¶

Hãy thêm một phương thức

class Point:
    "Point class for storing mathematical points."
24, phương thức này sẽ tăng một thể hiện thời gian theo một số giây nhất định. Để tiết kiệm dung lượng, chúng tôi sẽ tiếp tục loại bỏ các phương thức đã xác định trước đó, nhưng bạn phải luôn giữ chúng trong phiên bản của mình

print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
47

Bây giờ chúng ta có thể gọi

class Point:
    "Point class for storing mathematical points."
24 trong một trường hợp thời gian

print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
48

Một lần nữa, đối tượng mà phương thức được gọi sẽ được gán cho tham số đầu tiên,

print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
10. Tham số thứ hai,
class Point:
    "Point class for storing mathematical points."
22 nhận giá trị
class Point:
    "Point class for storing mathematical points."
28

7. 10. Ví dụ với hai class Point: "Point class for storing mathematical points." 08¶

Hãy thêm một phương thức boolen,

class Point:
    "Point class for storing mathematical points."
30, nhận hai trường hợp thời gian và trả về
class Point:
    "Point class for storing mathematical points."
31 khi trường hợp đầu tiên theo thứ tự thời gian sau trường hợp thứ hai

Chúng tôi chỉ có thể chuyển đổi một trong các tham số thành

print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
10;

print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
49

Chúng tôi gọi phương thức này trên một đối tượng và chuyển đối tượng kia làm đối số

print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
80

Bạn gần như có thể đọc lời kêu gọi như tiếng Anh. Nếu thời gian 1 sau thời gian 2, thì…

7. 10. 1. Hàm thuần túy và công cụ sửa đổi (lại)¶

Trong vài phần tiếp theo, chúng ta sẽ viết hai phiên bản của hàm có tên là

class Point:
    "Point class for storing mathematical points."
34, tính tổng của hai số
class Point:
    "Point class for storing mathematical points."
08. Họ sẽ chứng minh hai loại chức năng. các hàm thuần túy và công cụ sửa đổi mà chúng ta đã gặp lần đầu tiên trong chương Hàm .

Sau đây là phiên bản thô của

class Point:
    "Point class for storing mathematical points."
34

print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
81

Hàm tạo một đối tượng

class Point:
    "Point class for storing mathematical points."
08 mới, khởi tạo các thuộc tính của nó và trả về một tham chiếu đến đối tượng mới. Đây được gọi là một hàm thuần túy vì nó không sửa đổi bất kỳ đối tượng nào được truyền cho nó dưới dạng tham số và nó không có tác dụng phụ, chẳng hạn như hiển thị giá trị hoặc nhận đầu vào của người dùng

Dưới đây là một ví dụ về cách sử dụng chức năng này. Chúng ta sẽ tạo hai đối tượng

class Point:
    "Point class for storing mathematical points."
08.
class Point:
    "Point class for storing mathematical points."
39, chứa thời gian hiện tại; . Sau đó, chúng tôi sẽ sử dụng
class Point:
    "Point class for storing mathematical points."
34 để biết khi nào bánh mì sẽ được làm xong. Nếu bạn chưa viết xong ________ 911, hãy xem trước Phần trước khi bạn thử điều này

print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
82

Đầu ra của chương trình này là

class Point:
    "Point class for storing mathematical points."
43, đúng. Mặt khác, có trường hợp kết quả không chính xác. Bạn có thể nghĩ về một?

Vấn đề là chức năng này không xử lý các trường hợp trong đó số giây hoặc phút cộng lại lớn hơn sáu mươi. Khi điều đó xảy ra, chúng ta phải chuyển số giây thừa vào cột phút hoặc số phút thừa vào cột giờ

Đây là phiên bản sửa lỗi thứ hai của chức năng

print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
83

Mặc dù chức năng này là chính xác, nhưng nó đang bắt đầu lớn. Sau đó, chúng tôi sẽ đề xuất một cách tiếp cận thay thế mang lại mã ngắn hơn

7. 10. 2. Công cụ sửa đổi¶

Đôi khi, một hàm sẽ hữu ích khi sửa đổi một hoặc nhiều đối tượng mà nó nhận làm tham số. Thông thường, người gọi giữ một tham chiếu đến các đối tượng mà nó đi qua, vì vậy bất kỳ thay đổi nào mà chức năng tạo ra đều hiển thị cho người gọi. Các chức năng hoạt động theo cách này được gọi là công cụ sửa đổi

class Point:
    "Point class for storing mathematical points."
24, thêm một số giây nhất định vào đối tượng
class Point:
    "Point class for storing mathematical points."
08, sẽ được viết một cách tự nhiên nhất dưới dạng bổ ngữ. Một bản nháp sơ bộ của chức năng trông như thế này

print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
84

Dòng đầu tiên thực hiện thao tác cơ bản;

Chức năng này có đúng không? . Một giải pháp là thay thế câu lệnh

class Point:
    "Point class for storing mathematical points."
48 bằng câu lệnh
class Point:
    "Point class for storing mathematical points."
49

print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
85

Chức năng này hiện đã chính xác, nhưng nó không phải là giải pháp hiệu quả nhất

7. 11. Phát triển nguyên mẫu so với lập kế hoạch¶

Cho đến giờ trong chương này, chúng ta đã sử dụng một cách tiếp cận để phát triển chương trình mà chúng ta sẽ gọi là phát triển nguyên mẫu. Chúng tôi đã viết một bản nháp sơ bộ (hoặc nguyên mẫu) để thực hiện tính toán cơ bản và sau đó thử nghiệm nó trên một số trường hợp, sửa các lỗi khi chúng tôi tìm thấy chúng

Mặc dù cách tiếp cận này có thể hiệu quả, nhưng nó có thể dẫn đến mã phức tạp không cần thiết – vì nó xử lý nhiều trường hợp đặc biệt – và không đáng tin cậy – vì khó biết liệu chúng ta có tìm thấy tất cả các lỗi hay không

Một giải pháp thay thế là phát triển theo kế hoạch, trong đó hiểu biết sâu sắc về vấn đề có thể giúp lập trình dễ dàng hơn nhiều. Trong trường hợp này, cái nhìn sâu sắc là một đối tượng

class Point:
    "Point class for storing mathematical points."
08 thực sự là một số có ba chữ số trong cơ số 60. Thành phần
class Point:
    "Point class for storing mathematical points."
51 là cột đơn vị, thành phần
class Point:
    "Point class for storing mathematical points."
52 là cột sáu mươi và thành phần
class Point:
    "Point class for storing mathematical points."
53 là cột ba mươi sáu hàng trăm

Khi chúng tôi viết

class Point:
    "Point class for storing mathematical points."
34 và
class Point:
    "Point class for storing mathematical points."
24, chúng tôi đã thực hiện phép cộng trong cơ số 60 một cách hiệu quả, đó là lý do tại sao chúng tôi phải thực hiện từ cột này sang cột tiếp theo

Quan sát này gợi ý một cách tiếp cận khác cho toàn bộ vấn đề – chúng ta có thể chuyển đổi một đối tượng

class Point:
    "Point class for storing mathematical points."
08 thành một số duy nhất và tận dụng thực tế là máy tính biết cách thực hiện phép tính số học với các số. Hàm sau đây chuyển đổi một đối tượng
class Point:
    "Point class for storing mathematical points."
08 thành một số nguyên

print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
86

Bây giờ, tất cả những gì chúng ta cần là một cách để chuyển đổi từ một số nguyên thành một đối tượng

class Point:
    "Point class for storing mathematical points."
08

print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
87

Bạn có thể phải suy nghĩ một chút để thuyết phục bản thân rằng kỹ thuật chuyển đổi từ cơ sở này sang cơ sở khác là đúng. Giả sử bạn bị thuyết phục, bạn có thể sử dụng các chức năng này để viết lại

class Point:
    "Point class for storing mathematical points."
34

print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
88

Phiên bản này ngắn hơn nhiều so với phiên bản gốc và việc chứng minh rằng nó đúng sẽ dễ dàng hơn nhiều (giả sử, như thường lệ, các chức năng mà nó gọi là đúng)

7. 12. Tổng quát hóa¶

Theo một số cách, việc chuyển đổi từ cơ số 60 sang cơ số 10 và ngược lại khó hơn là chỉ xử lý thời gian. Chuyển đổi cơ sở trừu tượng hơn;

Nhưng nếu chúng ta có cái nhìn sâu sắc để coi thời gian là các số cơ bản 60 và đầu tư vào việc viết các hàm chuyển đổi (

class Point:
    "Point class for storing mathematical points."
60 và
class Point:
    "Point class for storing mathematical points."
61), chúng ta sẽ có được một chương trình ngắn hơn, dễ đọc và gỡ lỗi hơn, đồng thời đáng tin cậy hơn

Việc thêm các tính năng sau này cũng dễ dàng hơn. Ví dụ: hãy tưởng tượng trừ hai

class Point:
    "Point class for storing mathematical points."
08 để tìm khoảng thời gian giữa chúng. Cách tiếp cận ngây thơ sẽ là thực hiện phép trừ với việc vay. Sử dụng các chức năng chuyển đổi sẽ dễ dàng hơn và có nhiều khả năng đúng hơn

Trớ trêu thay, đôi khi làm cho một vấn đề trở nên khó hơn (hoặc tổng quát hơn) lại khiến nó trở nên dễ dàng hơn (vì có ít trường hợp đặc biệt hơn và ít cơ hội mắc lỗi hơn)

7. 13. Thuật toán¶

Khi bạn viết một giải pháp chung cho một loại vấn đề, trái ngược với một giải pháp cụ thể cho một vấn đề đơn lẻ, bạn đã viết một thuật toán. Trước đây chúng ta có nhắc đến từ này nhưng chưa định nghĩa kỹ. Không dễ để xác định, vì vậy chúng tôi sẽ thử một vài cách tiếp cận

Đầu tiên, hãy xem xét thứ gì đó không phải là thuật toán. Khi bạn học cách nhân các số có một chữ số, có lẽ bạn đã thuộc lòng bảng cửu chương. Trên thực tế, bạn đã ghi nhớ 100 giải pháp cụ thể. Đó là loại kiến ​​​​thức không phải là thuật toán

Nhưng nếu bạn lười biếng, bạn có thể bị lừa bằng cách học một vài thủ thuật. Ví dụ: để tìm tích của

class Point:
    "Point class for storing mathematical points."
63 và 9, bạn có thể viết
class Point:
    "Point class for storing mathematical points."
64 là chữ số đầu tiên và
class Point:
    "Point class for storing mathematical points."
65 là chữ số thứ hai. Thủ thuật này là một giải pháp chung để nhân bất kỳ số có một chữ số nào với 9. Đó là một thuật toán

Tương tự như vậy, các kỹ thuật bạn đã học để cộng có mang, trừ có mượn và chia dài đều là các thuật toán. Một trong những đặc điểm của thuật toán là chúng không yêu cầu bất kỳ trí thông minh nào để thực hiện. Chúng là các quy trình cơ học, trong đó mỗi bước nối tiếp bước trước theo một bộ quy tắc đơn giản.

Theo tôi, thật đáng xấu hổ khi con người dành quá nhiều thời gian ở trường để học cách thực hiện các thuật toán mà theo đúng nghĩa đen là không cần trí thông minh

Mặt khác, quá trình thiết kế thuật toán rất thú vị, thách thức trí tuệ và là phần trung tâm của cái mà chúng ta gọi là lập trình

Một số điều mà mọi người làm một cách tự nhiên, không gặp khó khăn hoặc suy nghĩ có ý thức, lại là điều khó diễn đạt nhất bằng thuật toán. Hiểu ngôn ngữ tự nhiên là một ví dụ điển hình. Tất cả chúng ta đều làm điều đó, nhưng cho đến nay không ai có thể giải thích cách chúng ta làm điều đó, ít nhất là không phải dưới dạng thuật toán

7. 14. Điểm xem lại¶

Hãy viết lại lớp

print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
5 theo phong cách hướng đối tượng hơn

print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
89

Phương thức tiếp theo,

class Point:
    "Point class for storing mathematical points."
67, trả về một biểu diễn chuỗi của đối tượng
print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
5. Nếu một lớp cung cấp một phương thức có tên là
class Point:
    "Point class for storing mathematical points."
67, thì nó sẽ ghi đè hành vi mặc định của hàm
class Point:
    "Point class for storing mathematical points."
70 tích hợp trong Python

print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
20

In một đối tượng

print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
5 gọi ngầm
class Point:
    "Point class for storing mathematical points."
67 trên đối tượng, do đó, việc xác định
class Point:
    "Point class for storing mathematical points."
67 cũng thay đổi hành vi của
class Point:
    "Point class for storing mathematical points."
74

print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
21

Khi chúng ta viết một lớp mới, hầu như chúng ta luôn bắt đầu bằng cách viết

print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
15, giúp khởi tạo đối tượng dễ dàng hơn và
class Point:
    "Point class for storing mathematical points."
67, hầu như luôn hữu ích cho việc gỡ lỗi

7. 15. Nạp toán tử¶

Một số ngôn ngữ cho phép thay đổi định nghĩa của các toán tử tích hợp khi chúng được áp dụng cho các loại do người dùng xác định. Tính năng này được gọi là quá tải toán tử. Nó đặc biệt hữu ích khi xác định các loại toán học mới

Ví dụ: để ghi đè toán tử cộng

class Point:
    "Point class for storing mathematical points."
77, chúng tôi cung cấp một phương thức có tên
class Point:
    "Point class for storing mathematical points."
78

print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
22

Như thường lệ, tham số đầu tiên là đối tượng mà phương thức được gọi. Tham số thứ hai được đặt tên thuận tiện là

class Point:
    "Point class for storing mathematical points."
33 để phân biệt với
print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
10. Để thêm hai
print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
5, chúng tôi tạo và trả về một
print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
5 mới chứa tổng của tọa độ
print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
8 và tổng của tọa độ
print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
9

Bây giờ, khi chúng ta áp dụng toán tử

class Point:
    "Point class for storing mathematical points."
77 cho các đối tượng
print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
5, Python sẽ gọi
class Point:
    "Point class for storing mathematical points."
78

print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
23

Biểu thức

class Point:
    "Point class for storing mathematical points."
88 tương đương với
class Point:
    "Point class for storing mathematical points."
89, nhưng rõ ràng là tao nhã hơn. Như một bài tập, hãy thêm một phương thức
class Point:
    "Point class for storing mathematical points."
90 làm quá tải toán tử trừ và dùng thử. Có một số cách để ghi đè hành vi của toán tử nhân. bằng cách định nghĩa một phương thức có tên là
class Point:
    "Point class for storing mathematical points."
91 hoặc
class Point:
    "Point class for storing mathematical points."
92 hoặc cả hai

Nếu toán hạng bên trái của

class Point:
    "Point class for storing mathematical points."
93 là một
print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
5, Python gọi
class Point:
    "Point class for storing mathematical points."
91, giả định rằng toán hạng kia cũng là một
print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
5. Nó tính tích vô hướng của hai điểm, được xác định theo các quy tắc của đại số tuyến tính

print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
24

Nếu toán hạng bên trái của

class Point:
    "Point class for storing mathematical points."
93 là kiểu nguyên thủy và toán hạng bên phải là một
print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
5, Python gọi
class Point:
    "Point class for storing mathematical points."
92, thực hiện phép nhân vô hướng

print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
25

Kết quả là một

print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
5 mới có tọa độ là bội số của tọa độ ban đầu. Nếu
class Point:
    "Point class for storing mathematical points."
33 là loại không thể nhân với số dấu phẩy động, thì
class Point:
    "Point class for storing mathematical points."
92 sẽ sinh ra lỗi

Ví dụ này minh họa cả hai loại phép nhân

print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
26

Điều gì xảy ra nếu chúng ta cố gắng đánh giá

print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
403? . Bên trong
class Point:
    "Point class for storing mathematical points."
91, chương trình cố gắng truy cập tọa độ
print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
8 của
class Point:
    "Point class for storing mathematical points."
33, không thành công vì một số nguyên không có thuộc tính

print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
27

Thật không may, thông báo lỗi hơi mờ. Ví dụ này cho thấy một số khó khăn của lập trình hướng đối tượng. Đôi khi thật khó để tìm ra mã nào đang chạy

Để có ví dụ đầy đủ hơn về nạp chồng toán tử, xem Phụ lục (nạp chồng tham chiếu)

7. 16. Đa hình¶

Hầu hết các phương pháp chúng tôi đã viết chỉ hoạt động cho một loại cụ thể. Khi bạn tạo một đối tượng mới, bạn viết các phương thức hoạt động trên loại đó

Nhưng có một số phép toán mà bạn sẽ muốn áp dụng cho nhiều loại, chẳng hạn như các phép toán số học trong các phần trước. Nếu nhiều loại hỗ trợ cùng một nhóm thao tác, bạn có thể viết các hàm hoạt động trên bất kỳ loại nào trong số đó

Ví dụ, phép toán

print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
410 (phổ biến trong đại số tuyến tính) nhận ba tham số; . Chúng ta có thể viết nó bằng Python như thế này

print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
28

Phương pháp này sẽ hoạt động đối với bất kỳ giá trị nào của

print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
8 và
print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
9 có thể được nhân lên và đối với bất kỳ giá trị nào của
print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
413 có thể được thêm vào sản phẩm

Chúng ta có thể gọi nó với các giá trị số

print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
29

Hoặc với

print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
5s

print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
0

Trong trường hợp đầu tiên,

print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
5 được nhân với một số vô hướng và sau đó được cộng với một
print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
5 khác. Trong trường hợp thứ hai, tích vô hướng mang lại một giá trị số, vì vậy tham số thứ ba cũng phải là một giá trị số

Một chức năng như thế này có thể nhận các tham số với các loại khác nhau được gọi là đa hình

Một ví dụ khác, xem xét phương thức

print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
417, in danh sách hai lần, tiến và lùi

print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
1

Bởi vì phương pháp

print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
418 là một công cụ sửa đổi, chúng tôi tạo một bản sao của danh sách trước khi đảo ngược nó. Theo cách đó, phương thức này không sửa đổi danh sách mà nó nhận được dưới dạng tham số

Đây là một ví dụ áp dụng

print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
417 cho một danh sách

print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
2

Tất nhiên, chúng tôi dự định áp dụng chức năng này cho các danh sách, vì vậy không có gì ngạc nhiên khi nó hoạt động. Điều đáng ngạc nhiên là nếu chúng ta có thể áp dụng nó vào một

print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
5

Để xác định xem một chức năng có thể được áp dụng cho một loại mới hay không, chúng tôi áp dụng quy tắc cơ bản của tính đa hình. Nếu tất cả các hoạt động bên trong hàm có thể được áp dụng cho loại, thì hàm có thể được áp dụng cho loại. Các hoạt động trong phương pháp bao gồm

print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
421,
print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
418 và
class Point:
    "Point class for storing mathematical points."
74

print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
421 hoạt động trên bất kỳ đối tượng nào và chúng tôi đã viết một phương thức
class Point:
    "Point class for storing mathematical points."
67 cho các
print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
5, vì vậy tất cả những gì chúng tôi cần là một phương thức
print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
418 trong lớp
print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
5

print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
3

Sau đó, chúng ta có thể chuyển

print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
5s đến
print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
417

print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
4

Loại đa hình tốt nhất là loại không cố ý, trong đó bạn phát hiện ra rằng một chức năng bạn đã viết có thể được áp dụng cho một loại mà bạn chưa bao giờ lên kế hoạch.

7. 17. Bảng thuật ngữ¶

lớp

Loại hợp chất do người dùng xác định. Một lớp cũng có thể được coi là khuôn mẫu cho các đối tượng là thể hiện của nó

khởi tạo

Để tạo một thể hiện của một lớp

ví dụ

Một đối tượng thuộc về một lớp

sự vật

Một kiểu dữ liệu phức hợp thường được sử dụng để mô hình hóa một sự vật hoặc khái niệm trong thế giới thực

thuộc tính

Một trong những mục dữ liệu được đặt tên tạo nên một thể hiện

chức năng thuần túy

Một hàm không sửa đổi bất kỳ đối tượng nào mà nó nhận làm tham số. Hầu hết các hàm thuần túy đều hiệu quả

bổ nghĩa

Hàm thay đổi một hoặc nhiều đối tượng mà nó nhận làm tham số. Hầu hết các công cụ sửa đổi đều vô hiệu

phong cách lập trình chức năng

Một phong cách thiết kế chương trình trong đó phần lớn các chức năng là thuần túy

phát triển nguyên mẫu

Một cách để phát triển các chương trình bắt đầu với một nguyên mẫu và dần dần thử nghiệm và cải tiến nó

kế hoạch phát triển

Một cách phát triển các chương trình liên quan đến hiểu biết sâu sắc về vấn đề và lập kế hoạch nhiều hơn so với phát triển gia tăng hoặc phát triển nguyên mẫu

ngôn ngữ hướng đối tượng

Một ngôn ngữ cung cấp các tính năng, chẳng hạn như lớp do người dùng định nghĩa và tính kế thừa, hỗ trợ lập trình hướng đối tượng

lập trình hướng đối tượng

Một phong cách lập trình trong đó dữ liệu và các hoạt động thao tác với nó được tổ chức thành các lớp và phương thức

phương pháp

Một hàm được định nghĩa bên trong một định nghĩa lớp và được gọi trên các phiên bản của lớp đó. . ghi đè. Để thay thế một mặc định. Các ví dụ bao gồm thay thế một tham số mặc định bằng một đối số cụ thể và thay thế một phương thức mặc định bằng cách cung cấp một phương thức mới có cùng tên

phương thức khởi tạo

Một phương thức đặc biệt được gọi tự động khi một đối tượng mới được tạo và khởi tạo các thuộc tính của đối tượng

quá tải toán tử

Mở rộng các toán tử tích hợp sẵn (

class Point:
    "Point class for storing mathematical points."
77,
print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
432,
class Point:
    "Point class for storing mathematical points."
93,
print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
434,
print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
435, v.v. ) để chúng hoạt động với các loại do người dùng xác định

sản phẩm chấm

Một phép toán được xác định trong đại số tuyến tính nhân hai

print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
5 và mang lại một giá trị số

nhân bản vô tính

Một phép toán được định nghĩa trong đại số tuyến tính nhân mỗi tọa độ của một

print('({0}, {1})'.format(p.x, p.y))
distance_squared = p.x * p.x + p.y * p.y
5 với một giá trị số

đa hình

Một chức năng có thể hoạt động trên nhiều loại. Nếu tất cả các hoạt động trong một hàm có thể được áp dụng cho một loại, thì hàm đó có thể được áp dụng cho một loại

Điều gì đúng về thuộc tính lớp?

Thuộc tính của lớp là thuộc tính do chính lớp đó sở hữu . Chúng sẽ được chia sẻ bởi tất cả các thể hiện của lớp. Do đó, chúng có cùng giá trị cho mọi trường hợp. Chúng tôi định nghĩa các thuộc tính lớp bên ngoài tất cả các phương thức, thường chúng được đặt ở trên cùng, ngay bên dưới tiêu đề lớp.

Điều gì đúng về lớp và đối tượng?

Lớp trong Python là gì?

Các lớp và đối tượng Python . Hầu hết mọi thứ trong Python là một đối tượng, với các thuộc tính và phương thức của nó. Lớp giống như một hàm tạo đối tượng hoặc "bản thiết kế" để tạo đối tượng .

Điều gì đúng về phương thức __ Init__ trong Python?

Phương thức __init__ tương đương với Python của hàm tạo C++ theo cách tiếp cận hướng đối tượng. Hàm __init__ được gọi mỗi khi một đối tượng được tạo từ một lớp. Phương thức __init__ cho phép lớp khởi tạo các thuộc tính của đối tượng và không phục vụ mục đích nào khác . Nó chỉ được sử dụng trong các lớp học.