Bạn đang xem : python 3 lớp mới

Các lớp cung cấp một phương tiện để nhóm dữ liệu và chức năng lại với nhau. Đang tạo
một lớp mới tạo ra một loại đối tượng mới, cho phép các thể hiện mới của đối tượng đó
loại được thực hiện. Mỗi cá thể lớp có thể có các thuộc tính được đính kèm với nó để
duy trì trạng thái của nó. Các cá thể lớp cũng có thể có các phương thức (được định nghĩa bởi
lớp) để sửa đổi trạng thái của nó.

So với các ngôn ngữ lập trình khác, cơ chế lớp của Python thêm các lớp
với tối thiểu cú pháp và ngữ nghĩa mới. Nó là một hỗn hợp của lớp
cơ chế được tìm thấy trong C ++ và Modula-3. Các lớp Python cung cấp tất cả các tiêu chuẩn
các tính năng của Lập trình hướng đối tượng: cơ chế kế thừa lớp cho phép
nhiều lớp cơ sở, một lớp dẫn xuất có thể ghi đè lên bất kỳ phương thức nào của lớp cơ sở của nó
lớp hoặc các lớp và một phương thức có thể gọi phương thức của một lớp cơ sở với cùng
Tên. Các đối tượng có thể chứa số lượng và loại dữ liệu tùy ý. Như đúng với
mô-đun, lớp tham gia vào bản chất động của Python: chúng được tạo tại
thời gian chạy và có thể được sửa đổi thêm sau khi tạo.

Trong thuật ngữ C ++, thông thường các thành viên lớp (bao gồm cả các thành viên dữ liệu) là
công khai (ngoại trừ xem bên dưới Biến riêng ) và tất cả các hàm thành viên là
ảo. Như trong Modula-3, không có lối tắt nào để tham chiếu đến đối tượng
các thành viên từ các phương thức của nó: hàm phương thức được khai báo với một
đối số đại diện cho đối tượng, được cung cấp ngầm bởi cuộc gọi. Như
trong Smalltalk, bản thân các lớp là các đối tượng. Điều này cung cấp ngữ nghĩa cho
nhập và đổi tên. Không giống như C ++ và Modula-3, các kiểu tích hợp có thể được sử dụng như
các lớp cơ sở cho phần mở rộng của người dùng. Ngoài ra, giống như trong C ++, hầu hết các
toán tử với cú pháp đặc biệt (toán tử số học, chỉ số con, v.v.) có thể
được xác định lại cho các phiên bản của lớp.

(Thiếu thuật ngữ được chấp nhận rộng rãi để nói về các lớp học, tôi sẽ làm
không thường xuyên sử dụng các điều khoản Smalltalk và C ++. Tôi sẽ sử dụng các thuật ngữ Modula-3, vì
ngữ nghĩa hướng đối tượng của nó gần với ngữ nghĩa của Python hơn là C ++, nhưng tôi
hy vọng rằng ít độc giả đã nghe nói về nó.)

9.1.

Lời giới thiệu về tên và đối tượng

Các đối tượng có tính riêng lẻ và nhiều tên (trong nhiều phạm vi) có thể bị ràng buộc
cho cùng một đối tượng. Điều này được gọi là bí danh trong các ngôn ngữ khác. Đây là
thường không được đánh giá cao trong cái nhìn đầu tiên về Python và có thể được bỏ qua một cách an toàn
khi xử lý các kiểu cơ bản bất biến (số, chuỗi, bộ giá trị). Tuy nhiên,
răng cưa có thể có tác động đáng ngạc nhiên đến ngữ nghĩa của mã Python
liên quan đến các đối tượng có thể thay đổi như danh sách, từ điển và hầu hết các loại khác.
Điều này thường được sử dụng vì lợi ích của chương trình, vì các bí danh hoạt động như
con trỏ ở một số khía cạnh. Ví dụ: truyền một đối tượng là rẻ vì chỉ một
con trỏ được thông qua bởi việc thực hiện; và nếu một hàm sửa đổi một đối tượng
được truyền dưới dạng đối số, người gọi sẽ thấy sự thay đổi – điều này loại bỏ
cần hai cơ chế truyền đối số khác nhau như trong Pascal.

9.2.

Phạm vi và Không gian tên trong Python

Trước khi giới thiệu các lớp học, trước tiên tôi phải cho bạn biết vài điều về Python
quy tắc phạm vi. Định nghĩa lớp chơi một số thủ thuật gọn gàng với không gian tên, và bạn
cần biết phạm vi và không gian tên hoạt động như thế nào để hiểu đầy đủ những gì đang diễn ra.
Ngẫu nhiên, kiến ​​thức về chủ đề này rất hữu ích cho bất kỳ Python nâng cao nào
lập trình viên.

Hãy bắt đầu với một số định nghĩa.

Không gian tên là một ánh xạ từ tên đến các đối tượng. Hầu hết các không gian tên hiện tại
được triển khai dưới dạng từ điển Python, nhưng điều đó thường không đáng chú ý trong bất kỳ
(ngoại trừ hiệu suất), và nó có thể thay đổi trong tương lai. Ví dụ về
không gian tên là: tập hợp các tên dựng sẵn (chứa các hàm như abs ()
tên ngoại lệ dựng sẵn); tên chung trong một mô-đun; và tên địa phương trong
một lời gọi hàm. Theo một nghĩa nào đó, tập hợp các thuộc tính của một đối tượng cũng hình thành
một không gian tên. Điều quan trọng cần biết về không gian tên là có
hoàn toàn không có sự liên quan giữa các tên trong các không gian tên khác nhau; ví dụ, hai
các mô-đun khác nhau đều có thể xác định một hàm tối đa hóa mà không gây nhầm lẫn -
người dùng mô-đun phải đặt tiền tố bằng tên mô-đun.

Nhân tiện, tôi sử dụng thuộc tính word cho bất kỳ tên nào sau dấu chấm - cho
ví dụ: trong biểu thức z.real , real là một thuộc tính của đối tượng
z . Nói một cách chính xác, tham chiếu đến tên trong mô-đun là thuộc tính
tham chiếu: trong biểu thức modname.funcname , modname là một mô-đun
đối tượng và funcname là một thuộc tính của nó. Trong trường hợp này, có
ánh xạ đơn giản giữa các thuộc tính của mô-đun và tên chung
được định nghĩa trong mô-đun: chúng chia sẻ cùng một không gian tên!

Các thuộc tính có thể ở chế độ chỉ đọc hoặc có thể ghi. Trong trường hợp thứ hai, giao cho
thuộc tính có thể. Thuộc tính mô-đun có thể ghi: bạn có thể viết
modname.the_answer = 42 . Các thuộc tính có thể ghi cũng có thể bị xóa với
Câu lệnh del . Ví dụ: del modname.the_answer sẽ xóa
thuộc tính the_answer từ đối tượng được đặt tên bởi modname .

Không gian tên được tạo vào những thời điểm khác nhau và có thời gian tồn tại khác nhau. Các
không gian tên chứa các tên dựng sẵn được tạo khi trình thông dịch Python
khởi động và không bao giờ bị xóa. Không gian tên chung cho một mô-đun được tạo
khi định nghĩa mô-đun được đọc trong; thông thường, không gian tên mô-đun cũng tồn tại
cho đến khi thông dịch viên thoát ra. Các câu lệnh được thực thi bởi cấp cao nhất
lệnh gọi của trình thông dịch, đọc từ tệp kịch bản hoặc tương tác,
được coi là một phần của mô-đun có tên __ main__ , vì vậy chúng có
không gian tên toàn cầu. (Các tên cài sẵn thực sự cũng nằm trong một mô-đun; đây là
được gọi là nội trang .)

Không gian tên cục bộ cho một hàm được tạo khi hàm được gọi và
bị xóa khi hàm trả về hoặc tăng một ngoại lệ không được xử lý
trong hàm. (Thực ra, quên sẽ là một cách tốt hơn để mô tả
những gì thực sự xảy ra.) Tất nhiên, mỗi lệnh gọi đệ quy đều có
không gian tên cục bộ.

Phạm vi là một vùng văn bản của chương trình Python nơi trực tiếp không gian tên
có thể truy cập. “Có thể truy cập trực tiếp” ở đây có nghĩa là tham chiếu không đủ tiêu chuẩn đến một
tên cố gắng tìm tên trong không gian tên.

Mặc dù phạm vi được xác định tĩnh, chúng được sử dụng động. Tại bất kỳ
thời gian trong khi thực thi, có 3 hoặc 4 phạm vi lồng nhau có không gian tên
có thể truy cập trực tiếp:

  • phạm vi trong cùng, được tìm kiếm đầu tiên, chứa các tên địa phương

  • phạm vi của bất kỳ hàm bao quanh nào, được tìm kiếm bắt đầu bằng
    phạm vi bao quanh gần nhất, chứa các tên không cục bộ nhưng cũng không toàn cục

  • phạm vi tiếp theo đến cuối cùng chứa các tên chung của mô-đun hiện tại

  • phạm vi ngoài cùng (được tìm kiếm cuối cùng) là không gian tên chứa các tên dựng sẵn

Nếu một tên được khai báo toàn cục, thì tất cả các tham chiếu và nhiệm vụ được chuyển trực tiếp đến
phạm vi ở giữa chứa các tên chung của mô-đun. Để gắn lại các biến
được tìm thấy bên ngoài phạm vi trong cùng, câu lệnh nonlocal có thể là
đã sử dụng; nếu không được khai báo là phi địa phương, các biến đó ở chế độ chỉ đọc (một nỗ lực
ghi vào một biến như vậy sẽ chỉ tạo một biến cục bộ mới trong
phạm vi trong cùng, giữ nguyên biến bên ngoài được đặt tên giống hệt nhau).

Thông thường, phạm vi địa phương tham chiếu đến tên địa phương của dòng điện (bằng văn bản)
hàm số. Bên ngoài các chức năng, phạm vi cục bộ tham chiếu đến cùng một không gian tên như
phạm vi toàn cầu: không gian tên của mô-đun. Định nghĩa lớp đặt một chỗ khác
không gian tên trong phạm vi cục bộ.

Điều quan trọng là nhận ra rằng phạm vi được xác định theo văn bản: toàn cầu
phạm vi của một chức năng được xác định trong một mô-đun là không gian tên của mô-đun đó, bất kể
từ đâu hoặc bằng bí danh nào mà hàm được gọi. Mặt khác,
thực tế tìm kiếm tên được thực hiện động, tại thời điểm chạy - tuy nhiên,
định nghĩa ngôn ngữ đang phát triển theo hướng phân giải tên tĩnh, tại "biên dịch"
thời gian, vì vậy đừng dựa vào độ phân giải tên động! (Trên thực tế, các biến cục bộ là
đã được xác định tĩnh.)

Một điểm đặc biệt của Python là - nếu không có global hoặc phi địa phương
câu lệnh đang có hiệu lực - các phép gán cho tên luôn đi vào phạm vi trong cùng.
Bài tập không sao chép dữ liệu - chúng chỉ liên kết tên với các đối tượng. Điều này cũng đúng
để xóa: câu lệnh del x xóa ràng buộc của x khỏi
không gian tên được tham chiếu bởi phạm vi cục bộ. Trên thực tế, tất cả các hoạt động giới thiệu
tên mới sử dụng phạm vi cục bộ: cụ thể là các câu lệnh nhập
định nghĩa chức năng ràng buộc mô-đun hoặc tên chức năng trong phạm vi cục bộ.

Câu lệnh global có thể được sử dụng để chỉ ra rằng
các biến sống trong phạm vi toàn cầu và sẽ được phục hồi ở đó; các
Câu lệnh nonlocal cho biết rằng các biến cụ thể đang tồn tại trong
một phạm vi bao quanh và sẽ được phục hồi ở đó.

9.2.1.

Phạm vi và Không gian tên Ví dụ

Đây là một ví dụ minh họa cách tham chiếu các phạm vi khác nhau và
không gian tên và cách thức global phi địa phương ảnh hưởng đến biến
ràng buộc:

 

def

scope_test

():

def

do_local

():

spam

=

"spam cục bộ"

def

do_nonlocal

():

phi địa phương

spam

spam

=

"spam phi địa phương"

def

do_global

():

toàn cầu

spam

spam

=

"spam toàn cầu"

spam

=

"kiểm tra spam"

do_local

()

print

(

"Sau khi gán cục bộ:"

,

spam

)

do_nonlocal

()

print

(

"Sau nhiệm vụ phi địa phương:"

,

spam

)

do_global

()

print

(

"Sau khi gán toàn cục:"

,

spam

)

scope_test

()

print

(

"Trong phạm vi toàn cầu:"

,

spam

)

Đầu ra của mã ví dụ là:

 

Sau nhiệm vụ cục bộ: kiểm tra spam Sau khi chỉ định phi địa phương: spam phi địa phương Sau khi chuyển nhượng toàn cầu: spam phi địa phương Trong phạm vi toàn cầu: spam toàn cầu

Lưu ý rằng cách phân công cục bộ (là mặc định) không thay đổi scope_test
ràng buộc của thư rác. Bài tập nonlocal đã thay đổi scope_test's
liên kết spam và bài tập global đã thay đổi cấp độ mô-đun
ràng buộc.

Bạn cũng có thể thấy rằng không có ràng buộc nào trước đây đối với thư rác trước
chuyển nhượng toàn cầu .

9.3.

Cái nhìn đầu tiên về lớp học

Các lớp giới thiệu một chút cú pháp mới, ba kiểu đối tượng mới và một số
ngữ nghĩa mới.

9.3.1.

Cú pháp Định nghĩa Lớp

Dạng định nghĩa lớp đơn giản nhất có dạng như sau:

 

class

ClassName

:

& lt;

câu lệnh

-

1 < / p>

& gt;

.

.

.

& lt;

câu lệnh

-

N < / p>

& gt;

Các định nghĩa lớp, như định nghĩa hàm (câu lệnh def )) phải thì là ở
được thực thi trước khi chúng có bất kỳ hiệu lực nào. (Có thể hình dung bạn có thể đặt một lớp học
định nghĩa trong một nhánh của câu lệnh if hoặc bên trong một hàm.)

Trong thực tế, các câu lệnh bên trong định nghĩa lớp thường sẽ là hàm
định nghĩa, nhưng các tuyên bố khác được cho phép và đôi khi hữu ích - chúng tôi sẽ
quay lại điều này sau. Các định nghĩa hàm bên trong một lớp thường có
một dạng danh sách đối số đặc biệt, được quy định bởi các quy ước gọi cho
phương pháp - một lần nữa, điều này sẽ được giải thích sau.

Khi định nghĩa lớp được nhập, một không gian tên mới sẽ được tạo và được sử dụng làm
phạm vi cục bộ - do đó, tất cả các phép gán cho các biến cục bộ sẽ chuyển sang
không gian tên. Đặc biệt, các định nghĩa hàm ràng buộc tên của
chức năng ở đây.

Khi định nghĩa lớp được để lại bình thường (thông qua phần cuối), một đối tượng lớp là
tạo. Về cơ bản, đây là một trình bao bọc xung quanh nội dung của không gian tên
được tạo bởi định nghĩa lớp; chúng ta sẽ tìm hiểu thêm về các đối tượng lớp trong
phần tiếp theo. Phạm vi cục bộ ban đầu (phạm vi có hiệu lực ngay trước lớp
định nghĩa đã được nhập) được phục hồi và đối tượng lớp được liên kết ở đây với
tên lớp được đưa ra trong tiêu đề định nghĩa lớp ( Tên lớp trong
ví dụ).

9.3.2.

Đối tượng Lớp

Đối tượng lớp hỗ trợ hai loại hoạt động: tham chiếu thuộc tính và
sự khởi tạo.

Tham chiếu thuộc tính sử dụng cú pháp chuẩn được sử dụng cho tất cả các tham chiếu thuộc tính
trong Python: obj.name . Các tên thuộc tính hợp lệ là tất cả các tên có trong
không gian tên của lớp khi đối tượng lớp được tạo. Vì vậy, nếu lớp
định nghĩa trông như thế này:

 

class

MyClass

:

"" "Một lớp mẫu đơn giản" ""

i

=

12345

def

f

(

tự

):

return

'hello world'

thì MyClass.i MyClass.f là các tham chiếu thuộc tính hợp lệ, trả về
một số nguyên và một đối tượng hàm, tương ứng. Thuộc tính lớp cũng có thể là
được gán cho, vì vậy bạn có thể thay đổi giá trị của MyClass.i bằng cách gán.
__ doc__ cũng là một thuộc tính hợp lệ, trả về chuỗi docstring thuộc về
lớp: "Một lớp mẫu đơn giản" .

Trình tạo lớp sử dụng ký hiệu hàm. Chỉ cần giả vờ rằng lớp học
đối tượng là một hàm không có tham số trả về một thể hiện mới của lớp.
Ví dụ (giả sử là lớp ở trên):

 

x

=

MyClass

< p class = "p"> ()

tạo một phiên bản mới của lớp và gán đối tượng này cho địa phương
biến x .

Hoạt động khởi tạo (“gọi” một đối tượng lớp) tạo ra một đối tượng trống.
Nhiều lớp muốn tạo các đối tượng với các phiên bản được tùy chỉnh cho một
trạng thái ban đầu. Do đó, một lớp có thể xác định một phương thức đặc biệt có tên
__ init __ () , như thế này:

 

def

__ init__

(

< p class = "bp"> tự

):

tự

.

dữ liệu

=

[]

Khi một lớp xác định một phương thức __ init __ () , thì lập trình lớp
tự động gọi __ init __ () cho phiên bản lớp mới được tạo. Vì thế
trong ví dụ này, một phiên bản mới, được khởi tạo có thể được lấy bằng:

 

x

=

MyClass

< p class = "p"> ()

Tất nhiên, phương thức __ init __ () có thể có đối số lớn hơn
Uyển chuyển. Trong trường hợp đó, các đối số được cung cấp cho toán tử khởi tạo lớp
được chuyển tới __ init __ () . Ví dụ:

 

& gt; & gt; & gt;

class

Phức tạp

:

...

def

__ init__

(

self

,

realpart

,

ảnh

):

...

tự

.

r

=

realpart

...

tự

.

i

=

hình ảnh

...

& gt; & gt; & gt;

x

=

Phức tạp

(

3.0

,

-

4,5

)

& gt; & gt; & gt;

x

.

r

,

x

.

i

(3.0, -4.5)

9.3.3.

Đối tượng Phiên bản

Bây giờ chúng ta có thể làm gì với các đối tượng cá thể? Các hoạt động duy nhất được hiểu bởi
các đối tượng instance là các tham chiếu thuộc tính. Có hai loại hợp lệ
tên thuộc tính: thuộc tính và phương thức dữ liệu.

thuộc tính dữ liệu tương ứng với “biến phiên bản” trong Smalltalk và “dữ liệu
thành viên ”trong C ++. Thuộc tính dữ liệu không cần khai báo; như các biến cục bộ,
chúng bắt đầu tồn tại khi chúng được chỉ định lần đầu tiên. Ví dụ, nếu
x là phiên bản của MyClass được tạo ở trên, phần sau của
mã sẽ in ra giá trị 16 , mà không để lại dấu vết:

 

x

.

bộ đếm

< p class = "o"> =

1

trong khi

x

.

truy cập

& lt;

10

:

x

.

bộ đếm

=

x

.

bộ đếm

*

2

print

(

x

.

bộ đếm

)

del

x

.

truy cập

Loại tham chiếu thuộc tính cá thể khác là một phương thức. Một phương pháp là một
chức năng “thuộc về” một đối tượng. (Trong Python, phương thức thuật ngữ không phải là duy nhất
đối với các thể hiện của lớp: các kiểu đối tượng khác cũng có thể có các phương thức. Ví dụ,
các đối tượng danh sách có các phương thức được gọi là nối thêm, chèn, loại bỏ, sắp xếp, v.v.
Tuy nhiên, trong cuộc thảo luận sau đây, chúng tôi sẽ sử dụng riêng phương pháp thuật ngữ để
nghĩa là các phương thức của các đối tượng cá thể lớp, trừ khi được nêu rõ ràng khác.)

Tên phương thức hợp lệ của một đối tượng cá thể phụ thuộc vào lớp của nó. Theo định nghĩa,
tất cả các thuộc tính của một lớp là các đối tượng hàm xác định tương ứng
phương pháp của các thể hiện của nó. Vì vậy, trong ví dụ của chúng tôi, x.f là một phương thức hợp lệ
tham chiếu, vì MyClass.f là một hàm, nhưng x.i thì không, vì
MyClass.i thì không. Nhưng x.f không giống với MyClass.f - nó
là một đối tượng phương thức, không phải là một đối tượng hàm.

9.3.4.

Đối tượng Phương thức

Thông thường, một phương thức được gọi ngay sau khi nó bị ràng buộc:

 

x

.

f

< p class = "p"> ()

Trong ví dụ MyClass , điều này sẽ trả về chuỗi 'hello world' .
Tuy nhiên, không cần thiết phải gọi một phương thức ngay lập tức: x.f là một phương thức
đối tượng, và có thể được lưu trữ và được gọi sau này. Ví dụ:

 

xf

=

x

< p class = "o">.

f

while

True

:

print

(

xf

())

sẽ tiếp tục in hello world cho đến hết thời gian.

Điều gì xảy ra chính xác khi một phương thức được gọi? Bạn có thể nhận thấy rằng
x.f () được gọi mà không có đối số ở trên, mặc dù hàm
định nghĩa cho f () đã chỉ định một đối số. Điều gì đã xảy ra với cuộc tranh cãi?
Chắc chắn Python đặt ra một ngoại lệ khi một hàm yêu cầu đối số là
được gọi mà không có bất kỳ - ngay cả khi đối số không thực sự được sử dụng…

Trên thực tế, bạn có thể đã đoán được câu trả lời: điều đặc biệt về các phương pháp là
mà đối tượng instance được chuyển làm đối số đầu tiên của hàm. Trong của chúng tôi
ví dụ, lệnh gọi x.f () hoàn toàn tương đương với MyClass.f (x) . Trong
nói chung, việc gọi một phương thức với danh sách n đối số tương đương với việc gọi
hàm tương ứng với danh sách đối số được tạo bằng cách chèn
đối tượng phiên bản của phương thức trước đối số đầu tiên.

Nếu bạn vẫn không hiểu cách hoạt động của các phương pháp, hãy xem cách triển khai có thể
có lẽ làm rõ vấn đề. Khi một thuộc tính không phải dữ liệu của một phiên bản là
được tham chiếu, lớp của cá thể được tìm kiếm. Nếu tên biểu thị một lớp hợp lệ
thuộc tính là một đối tượng hàm, một đối tượng phương thức được tạo bằng cách đóng gói
(trỏ tới) đối tượng instance và đối tượng hàm vừa được tìm thấy cùng nhau trong
một đối tượng trừu tượng: đây là đối tượng phương thức. Khi đối tượng phương thức được gọi
với một danh sách đối số, một danh sách đối số mới được tạo từ phiên bản
đối tượng và danh sách đối số và đối tượng hàm được gọi với
danh sách đối số.

9.3.5.

Các biến Lớp và Phiên bản

Nói chung, các biến phiên bản dành cho dữ liệu duy nhất cho mỗi phiên bản
và các biến lớp dành cho các thuộc tính và phương thức được chia sẻ bởi tất cả các trường hợp
của lớp:

 

class

Chó

:

kind

=

'canine'

# biến lớp được chia sẻ bởi tất cả các trường hợp

def

__ init__

(

self

,

tên

):

tự

.

tên

=

name

# biến phiên bản duy nhất cho mỗi phiên bản

& gt; & gt; & gt;

d

=

Con chó

(

'Fido'

)

& gt; & gt; & gt;

e

=

Con chó

(

'Bạn thân'

)

& gt; & gt; & gt;

d

.

kind

# được chia sẻ bởi tất cả các chú chó

'răng nanh'

& gt; & gt; & gt;

e

.

kind

# được chia sẻ bởi tất cả các chú chó

'răng nanh'

& gt; & gt; & gt;

d

.

tên

# duy nhất cho d

'Fido'

& gt; & gt; & gt;

e

.

tên

# duy nhất cho e

'Bạn thân'

Như đã thảo luận trong Lời về Tên và Đối tượng , dữ liệu được chia sẻ có thể gây ngạc nhiên
các hiệu ứng liên quan đến các đối tượng có thể thay đổi , chẳng hạn như danh sách và từ điển.
Ví dụ: danh sách thủ thuật trong đoạn mã sau không nên được sử dụng làm
biến lớp vì chỉ một danh sách duy nhất sẽ được chia sẻ bởi tất cả Dog
các trường hợp:

 

class

Chó

:

thủ thuật

=

[]

# nhầm lẫn sử dụng một biến lớp

def

__ init__

(

self

,

tên

):

tự

.

tên

=

tên

def

add_trick

(

self

,

lừa

):

self

.

thủ thuật

.

chắp thêm

(

lừa

)

& gt; & gt; & gt;

d

=

Con chó

(

'Fido'

)

& gt; & gt; & gt;

e

=

Con chó

(

'Bạn thân'

)

& gt; & gt; & gt;

d

.

add_trick

(

'cuộn qua'

)

& gt; & gt; & gt;

e

.

add_trick

(

'chơi chết'

)

& gt; & gt; & gt;

d

.

thủ thuật

# được chia sẻ bất ngờ bởi tất cả các chú chó

[

'cuộn qua'

,

'chơi chết đi'

]

Thiết kế đúng của lớp nên sử dụng biến phiên bản để thay thế:

 

class

Chó

:

def

__ init__

(

self

,

tên

):

tự

.

tên

=

tên

self

.

thủ thuật

=

[]

# tạo một danh sách trống mới cho từng chú chó

def

add_trick

(

self

,

lừa

):

self

.

thủ thuật

.

chắp thêm

(

lừa

)

& gt; & gt; & gt;

d

=

Con chó

(

'Fido'

)

& gt; & gt; & gt;

e

=

Con chó

(

'Bạn thân'

)

& gt; & gt; & gt;

d

.

add_trick

(

'cuộn qua'

)

& gt; & gt; & gt;

e

.

add_trick

(

'chơi chết'

)

& gt; & gt; & gt;

d

.

thủ thuật

[

'cuộn qua'

]

& gt; & gt; & gt;

e

.

thủ thuật

[

'chơi chết đi được'

]

9.4.

Nhận xét Ngẫu nhiên

Nếu cùng một tên thuộc tính xảy ra trong cả một trường hợp và trong một lớp,
thì việc tra cứu thuộc tính sẽ ưu tiên đối tượng:

 

& gt; & gt; & gt;

class

Kho

:

...

mục đích

=

' lưu trữ '

...

vùng

=

' phía tây '

...

& gt; & gt; & gt;

w1

=

Kho

()

& gt; & gt; & gt;

print

(

w1

.

mục đích

,

w1

.

vùng

)

lưu trữ phía tây

& gt; & gt; & gt;

w2

=

Kho

()

& gt; & gt; & gt;

w2

.

vùng

=

'đông'

& gt; & gt; & gt;

print

(

w2

.

mục đích

,

w2

.

vùng

)

kho đông

Các thuộc tính dữ liệu có thể được tham chiếu bởi các phương pháp cũng như bởi người dùng thông thường
("Khách hàng") của một đối tượng. Nói cách khác, các lớp không thể sử dụng để triển khai
các kiểu dữ liệu trừu tượng thuần túy. Trên thực tế, không có gì trong Python khiến nó có thể
thực thi ẩn dữ liệu - tất cả đều dựa trên quy ước. (Mặt khác,
triển khai Python, được viết bằng C, có thể ẩn hoàn toàn việc triển khai
chi tiết và kiểm soát quyền truy cập vào một đối tượng nếu cần thiết; cái này có thể được sử dụng bởi
phần mở rộng cho Python được viết bằng C.)

Khách hàng nên sử dụng các thuộc tính dữ liệu một cách cẩn thận - khách hàng có thể làm rối tung những điều bất biến
được duy trì bởi các phương pháp bằng cách đóng dấu vào các thuộc tính dữ liệu của chúng. Lưu ý rằng
khách hàng có thể thêm các thuộc tính dữ liệu của riêng họ vào một đối tượng cá thể mà không
ảnh hưởng đến hiệu lực của các phương thức, miễn là tránh được xung đột tên -
một lần nữa, quy ước đặt tên có thể giúp bạn bớt đau đầu ở đây.

Không có cách viết tắt nào để tham chiếu các thuộc tính dữ liệu (hoặc các phương pháp khác!) từ
trong các phương pháp. Tôi thấy rằng điều này thực sự làm tăng khả năng đọc của các phương pháp:
không có khả năng nhầm lẫn giữa các biến cục bộ và biến phiên bản khi
xem qua một phương pháp.

Thông thường, đối số đầu tiên của một phương thức được gọi là self . Đây không còn là gì nữa
hơn một quy ước: tên self hoàn toàn không có ý nghĩa đặc biệt đối với
Con trăn. Tuy nhiên, lưu ý rằng nếu không tuân theo quy ước, mã của bạn có thể
ít dễ đọc hơn đối với các lập trình viên Python khác và cũng có thể hình dung được rằng
chương trình trình duyệt lớp có thể được viết dựa trên quy ước như vậy.

Bất kỳ đối tượng hàm nào là thuộc tính lớp đều xác định phương thức cho các trường hợp của
lớp đó. Không nhất thiết phải định nghĩa hàm bằng văn bản
được bao gồm trong định nghĩa lớp: gán một đối tượng chức năng cho một cục bộ
biến trong lớp cũng ok. Ví dụ:

 

# Hàm được định nghĩa bên ngoài lớp

def

f1

(

tự

,

x

,

y

):

return

min

(

x

,

x

+

y

)

class

C

:

f

=

f1

def

g

(

tự

):

return

'hello world'

h

=

g

h
là tất cả các thuộc tính của lớp C tham chiếu đến các đối tượng hàm, và do đó chúng là tất cả các phương thức của các phiên bản của C - h chính xác tương đương với g . Lưu ý rằng thực hành này thường chỉ nhằm mục đích gây nhầm lẫn cho người đọc chương trình.

Các phương thức có thể gọi các phương thức khác bằng cách sử dụng các thuộc tính phương thức của self đối số:

 

class

Túi

:

def

__ init__

(

self

):

tự

.

dữ liệu

=

[]

def

thêm

(

tự

,

x

):

tự

.

dữ liệu

.

thêm vào

(

x

)

def

addtwice

(

self

,

x

):

tự

.

thêm

(

x

)

tự

.

thêm

(

x

)

Các phương thức có thể tham chiếu đến tên toàn cục giống như các hàm thông thường. Các
phạm vi toàn cục được liên kết với một phương thức là mô-đun chứa
Định nghĩa. (Một lớp không bao giờ được sử dụng như một phạm vi toàn cục.) Trong khi một
hiếm khi gặp phải một lý do chính đáng để sử dụng dữ liệu toàn cục trong một phương pháp, có
nhiều mục đích sử dụng hợp pháp trên phạm vi toàn cầu: đối với một thứ, các chức năng và mô-đun
được nhập vào phạm vi toàn cầu có thể được sử dụng bằng các phương thức, cũng như các hàm và
các lớp được định nghĩa trong đó. Thông thường, lớp chứa phương thức là chính nó
được xác định trong phạm vi toàn cầu này và trong phần tiếp theo, chúng tôi sẽ tìm thấy một số
lý do tại sao một phương thức muốn tham chiếu đến lớp của chính nó.

Mỗi giá trị là một đối tượng và do đó có một lớp (còn được gọi là kiểu của nó).
Nó được lưu trữ dưới dạng đối tượng .__ class__ .

9.5.

Kế thừa

Tất nhiên, một tính năng ngôn ngữ sẽ không xứng đáng với tên gọi "đẳng cấp" nếu không có
hỗ trợ thừa kế. Cú pháp cho định nghĩa lớp dẫn xuất trông giống như
cái này:

 

class

DerivedClassName

(

< p class = "n"> BaseClassName

):

& lt;

câu lệnh

-

1 < / p>

& gt;

.

.

.

& lt;

câu lệnh

-

N < / p>

& gt;

Tên BaseClassName phải được xác định trong phạm vi chứa
định nghĩa lớp dẫn xuất. Thay cho tên lớp cơ sở, tùy ý khác
biểu thức cũng được cho phép. Điều này có thể hữu ích, chẳng hạn như khi cơ sở
lớp được định nghĩa trong một mô-đun khác:

 

class

DerivedClassName

(

< p class = "n"> modname

.

BaseClassName

):

Việc thực thi một định nghĩa lớp dẫn xuất tiến hành giống như cho một lớp cơ sở.
Khi đối tượng lớp được xây dựng, lớp cơ sở được ghi nhớ. Đây là
được sử dụng để giải quyết các tham chiếu thuộc tính: nếu không tìm thấy thuộc tính được yêu cầu
trong lớp, việc tìm kiếm tiến hành tìm kiếm trong lớp cơ sở. Quy tắc này là
được áp dụng đệ quy nếu bản thân lớp cơ sở được dẫn xuất từ ​​một số lớp khác.

Không có gì đặc biệt về việc khởi tạo các lớp dẫn xuất:
DerivedClassName () tạo một phiên bản mới của lớp. Tham chiếu phương pháp
được giải quyết như sau: thuộc tính lớp tương ứng được tìm kiếm,
giảm dần chuỗi các lớp cơ sở nếu cần và tham chiếu phương thức
là hợp lệ nếu điều này mang lại một đối tượng hàm.

Các lớp có nguồn gốc có thể ghi đè các phương thức của các lớp cơ sở của chúng. Bởi vì các phương pháp
không có đặc quyền đặc biệt khi gọi các phương thức khác của cùng một đối tượng,
phương thức của một lớp cơ sở gọi một phương thức khác được định nghĩa trong cùng một lớp cơ sở
có thể kết thúc việc gọi một phương thức của một lớp dẫn xuất ghi đè nó. (Đối với C ++
lập trình viên: tất cả các phương thức trong Python đều là ảo một cách hiệu quả.)

Một phương thức ghi đè trong một lớp dẫn xuất trên thực tế có thể muốn mở rộng hơn là
chỉ cần thay thế phương thức lớp cơ sở cùng tên. Có một cách đơn giản để
gọi trực tiếp phương thức lớp cơ sở: chỉ cần gọi BaseClassName.methodname (self,
đối số)
. Điều này đôi khi cũng hữu ích cho khách hàng. (Lưu ý rằng điều này
chỉ hoạt động nếu lớp cơ sở có thể truy cập được dưới dạng BaseClassName trong toàn cục
phạm vi.)

Python có hai hàm tích hợp hoạt động với tính kế thừa:

  • Sử dụng isinstance () để kiểm tra kiểu của instance: isinstance (obj, int)
    sẽ là True chỉ khi obj .__ class__ int hoặc một số lớp
    bắt nguồn từ int .

  • Sử dụng Issubclass () để kiểm tra lớp kế thừa: Issubclass (bool, int)
    True bool là một lớp con của int . Tuy nhiên,
    Issubclass (float, int) Sai float không phải là
    lớp con của int .

9.5.1.

Thừa kế Nhiều người

Python cũng hỗ trợ một dạng đa kế thừa. Một định nghĩa lớp với
nhiều lớp cơ sở trông giống như sau:

 

class

DerivedClassName

(

< p class = "n"> Base1

,

Base2

,

Cơ sở 3

):

& lt;

câu lệnh

-

1 < / p>

& gt;

.

.

.

& lt;

câu lệnh

-

N < / p>

& gt;

Đối với hầu hết các mục đích, trong trường hợp đơn giản nhất, bạn có thể nghĩ đến việc tìm kiếm
các thuộc tính được kế thừa từ một lớp cha như là độ sâu đầu tiên, từ trái sang phải, không phải
tìm kiếm hai lần trong cùng một lớp, nơi có sự chồng chéo trong cấu trúc phân cấp.
Do đó, nếu một thuộc tính không được tìm thấy trong DerivedClassName , thì nó sẽ được tìm kiếm
cho trong Base1 , sau đó (đệ quy) trong các lớp cơ sở của Base1 ,
và nếu nó không được tìm thấy ở đó, nó sẽ được tìm kiếm trong Base2 , v.v.

Trên thực tế, nó phức tạp hơn thế một chút; thứ tự giải quyết phương pháp
thay đổi động để hỗ trợ các lệnh gọi hợp tác đến super () . Đây
phương pháp tiếp cận được biết đến trong một số ngôn ngữ đa kế thừa khác như
call-next-method và mạnh mẽ hơn super call được tìm thấy trong
ngôn ngữ kế thừa đơn.

Thứ tự động là cần thiết vì tất cả các trường hợp đa kế thừa đều thể hiện
một hoặc nhiều mối quan hệ kim cương (trong đó ít nhất một trong các lớp cha
có thể được truy cập thông qua nhiều đường dẫn từ lớp dưới cùng). Ví dụ,
tất cả các lớp kế thừa từ object , vì vậy mọi trường hợp đa kế thừa
cung cấp nhiều hơn một đường dẫn để tiếp cận đối tượng . Để giữ các lớp cơ sở
khỏi bị truy cập nhiều lần, thuật toán động sẽ tuyến tính hóa tìm kiếm
theo cách duy trì thứ tự từ trái sang phải được chỉ định trong mỗi
lớp, gọi mỗi cha một lần duy nhất và đó là đơn điệu (nghĩa là
lớp có thể được phân lớp mà không ảnh hưởng đến thứ tự ưu tiên của cha mẹ của nó).
Kết hợp với nhau, các đặc tính này giúp thiết kế có thể tin cậy và
các lớp có thể mở rộng với đa kế thừa. Để biết thêm chi tiết, hãy xem
https://www.python.org/download/releases/2.3/mro/ .

9.6.

Biến riêng

Các biến phiên bản “Riêng tư” không thể được truy cập ngoại trừ từ bên trong
đối tượng không tồn tại trong Python. Tuy nhiên, có một quy ước được tuân theo
bởi hầu hết mã Python: tên có tiền tố là dấu gạch dưới (ví dụ: _ spam ) nên
được coi là một phần không công khai của API (cho dù đó là một hàm, một phương thức
hoặc một thành viên dữ liệu). Nó nên được coi là một chi tiết và chủ đề thực hiện
thay đổi mà không cần thông báo.

Vì có một trường hợp sử dụng hợp lệ cho các thành viên lớp-private (cụ thể là tránh tên
xung đột tên với tên được xác định bởi các lớp con), hỗ trợ hạn chế cho
một cơ chế như vậy, được gọi là tên mangling. Bất kỳ số nhận dạng nào của biểu mẫu
__ spam (ít nhất hai dấu gạch dưới ở đầu, nhiều nhất một dấu gạch dưới ở cuối)
được thay thế bằng văn bản bằng _ classname__spam , trong đó classname
tên lớp hiện tại với (các) dấu gạch dưới ở đầu bị tước bỏ. Việc này đã hoàn thành
mà không cần quan tâm đến vị trí cú pháp của mã định danh, miễn là nó
xảy ra trong định nghĩa của một lớp.

Name mangling rất hữu ích để cho phép các lớp con ghi đè các phương thức mà không có
phá vỡ các cuộc gọi phương thức intraclass. Ví dụ:

 

class

Ánh xạ

:

def

__ init__

(

self

,

có thể lặp lại

):

self

.

items_list

=

[]

self

.

__ update

(

có thể lặp lại

)

def

cập nhật

(

tự

,

có thể lặp lại

):

cho

item

in

có thể lặp lại

:

tự

.

items_list

.

chắp thêm

(

item

)

__ update

=

update

# bản sao riêng tư của phương thức gốc update ()

class

MappingSubclass

(

Ánh xạ

):

def

cập nhật

(

tự

,

các khóa

,

giá trị

):

# cung cấp chữ ký mới cho bản cập nhật ()

# nhưng không phá vỡ __init __ ()

cho

item

in

zip

(

các khóa

,

giá trị

):

self

.

items_list

.

thêm vào

(

item

)

Ví dụ trên sẽ hoạt động ngay cả khi MappingSubclass giới thiệu một
định danh __ update vì nó được thay thế bằng _ Mapping__update trong
Lập bản đồ lớp _ MappingSubclass__update trong MappingSubclass
lớp tương ứng.

Lưu ý rằng các quy tắc xử lý sự cố được thiết kế chủ yếu để tránh tai nạn; Nó vẫn là
có thể truy cập hoặc sửa đổi một biến được coi là riêng tư. Cái này có thể
thậm chí hữu ích trong những trường hợp đặc biệt, chẳng hạn như trong trình gỡ lỗi.

Lưu ý rằng mã được chuyển đến exec () hoặc eval () không coi là
tên lớp của lớp gọi là lớp hiện tại; điều này tương tự như
hiệu ứng của câu lệnh toàn cầu , hiệu ứng của câu lệnh này cũng bị hạn chế
mã được biên dịch theo byte cùng nhau. Hạn chế tương tự áp dụng cho
getattr () , setattr () delattr () < / code>, cũng như khi tham chiếu
__ dict__ trực tiếp.

9.7.

Tỷ lệ cược và kết thúc

Đôi khi, sẽ hữu ích khi có kiểu dữ liệu tương tự như “bản ghi” hoặc C trong Pascal
"Struct", nhóm một vài mục dữ liệu được đặt tên lại với nhau. Định nghĩa lớp trống
sẽ làm tốt:

 

class

Nhân viên

:

vượt qua

john

=

Nhân viên

() < / p>

# Tạo hồ sơ nhân viên trống

# Điền vào các trường của bản ghi

john

.

tên

=

'John Doe'

john

.

dept

=

'phòng máy tính'

john

.

lương

=

1000

Một đoạn mã Python mong đợi một kiểu dữ liệu trừu tượng cụ thể thường có thể là
thay vào đó đã truyền một lớp mô phỏng các phương thức của kiểu dữ liệu đó. Vì
ví dụ, nếu bạn có một hàm định dạng một số dữ liệu từ một đối tượng tệp, bạn
có thể xác định một lớp bằng các phương thức read () readline () có được
dữ liệu từ bộ đệm chuỗi thay vào đó và chuyển nó dưới dạng đối số.

Các đối tượng của phương thức phiên bản cũng có các thuộc tính: m .__ self__ là phiên bản
đối tượng có phương thức m () m .__ func__ là đối tượng hàm
tương ứng với phương pháp.

9.8.

Các trình lặp

Bây giờ, bạn có thể nhận thấy rằng hầu hết các đối tượng vùng chứa có thể được lặp lại
sử dụng câu lệnh cho :

 

cho phần tử

trong

< p class = "p"> [

1

,

2

>

,

3

]:

print

(

phần tử

)

cho

phần tử

in

(

1

,

2

,

3

):

print

(

phần tử

)

cho

khóa

in

{

'one'

:

1

,

'hai'

:

2

}:

print

(

key

)

cho

char

in

"123"

:

print

(

char

)

cho

dòng

in

mở

(

"myfile.txt"

):

print

(

line

,

end

=

''

)

Phong cách truy cập này rõ ràng, ngắn gọn và thuận tiện. Việc sử dụng các trình vòng lặp
lan tỏa và thống nhất Python. Phía sau, câu lệnh for
gọi iter () trên đối tượng vùng chứa. Hàm trả về một trình lặp
đối tượng xác định phương thức __ next __ () truy cập
từng phần tử trong vùng chứa. Khi không còn phần tử nào nữa,
__ next __ () tăng một tham chiếu StopIteration ngoại lệ cho biết ngoại lệ
cho vòng lặp kết thúc. Bạn có thể gọi phương thức __ next __ ()
bằng cách sử dụng hàm tích hợp next () ; ví dụ này cho thấy cách hoạt động của tất cả:

 

& gt; & gt; & gt;

s

=

'abc'

& gt; & gt; & gt;

it

=

iter

(

s

)

& gt; & gt; & gt;

& lt; str_iterator đối tượng ở 0x10c90e650 & gt;

& gt; & gt; & gt;

tiếp theo

(

)

'a'

& gt; & gt; & gt;

tiếp theo

(

)

'b'

& gt; & gt; & gt;

tiếp theo

(

)

'c'

& gt; & gt; & gt;

tiếp theo

(

)

Traceback (lần gọi gần đây nhất):

Tệp

"& lt; stdin & gt;"

, dòng

1

, trong

& lt; module & gt;

tiếp theo

(

)

StopIteration

Khi đã nhìn thấy cơ chế đằng sau giao thức trình lặp, bạn có thể dễ dàng thêm
hành vi của trình lặp đối với các lớp của bạn. Xác định phương thức __ iter __ ()
trả về một đối tượng có phương thức __ next __ () . Nếu lớp
xác định __ next __ () , sau đó __ iter __ () chỉ có thể trả về self :

 

class

Đảo ngược

:

"" "Trình lặp để lặp lại một trình tự ngược lại." ""

def

__ init__

(

self

,

dữ liệu

):

tự

.

dữ liệu

=

dữ liệu

self

.

index

=

len

(

dữ liệu

)

def

__ iter__

(

self

):

trả về

tự

def

__ next__

(

self

):

if

self

.

index

==

0

:

nâng cao

StopIteration

self

.

index

=

self

.

index

-

1

trả về

tự

.

dữ liệu

[

tự

.

chỉ mục

]

 

& gt; & gt; & gt;

rev

=

Đảo ngược

(

'spam'

)

& gt; & gt; & gt;

iter

(

rev

)

& lt; __ main __. Đảo ngược đối tượng ở 0x00A1DB50 & gt;

& gt; & gt; & gt;

cho

char

in

rev

:

...

print

(

char

)

...

m

a

p

s

9.9.

Trình tạo

Trình tạo là một công cụ đơn giản và mạnh mẽ để tạo trình lặp. Họ
được viết giống như các hàm thông thường nhưng sử dụng câu lệnh output
bất cứ khi nào họ muốn trả lại dữ liệu. Mỗi lần next () được gọi trên đó,
Trình tạo tiếp tục lại nơi nó đã dừng lại (nó ghi nhớ tất cả các giá trị dữ liệu và
câu lệnh được thực thi lần cuối). Một ví dụ cho thấy rằng máy phát điện có thể được
dễ tạo:

 

def

ngược lại

(

< p class = "n"> dữ liệu

):

cho

chỉ mục

trong

phạm vi

(

len

(

dữ liệu

)

-

1

,

-

1

,

-

1

):

năng suất

dữ liệu

[

index

]

 

& gt; & gt; & gt;

cho

char

in

đảo ngược

(

'gôn'

):

...

print

(

char

)

...

f

l

o

g

Bất cứ điều gì có thể được thực hiện với trình tạo cũng có thể được thực hiện với dựa trên lớp
các trình vòng lặp như được mô tả trong phần trước. Điều gì làm cho máy phát điện trở nên như vậy
nhỏ gọn là __ iter __ () __ next __ ()
được tạo tự động.

Một tính năng chính khác là các biến cục bộ và trạng thái thực thi là
được lưu tự động giữa các cuộc gọi. Điều này làm cho hàm dễ viết hơn và
rõ ràng hơn nhiều so với cách tiếp cận sử dụng các biến phiên bản như self.index
self.data .

Ngoài việc tạo phương pháp tự động và lưu trạng thái chương trình, khi
trình tạo kết thúc, chúng tự động tăng StopIteration . Trong
kết hợp, các tính năng này giúp bạn dễ dàng tạo các trình vòng lặp mà không tốn nhiều công sức
hơn là viết một hàm thông thường.

9.10.

Biểu thức trình tạo

Một số trình tạo đơn giản có thể được mã hóa ngắn gọn dưới dạng biểu thức bằng cú pháp
tương tự như phần hiểu danh sách nhưng có dấu ngoặc đơn thay vì dấu ngoặc vuông.
Các biểu thức này được thiết kế cho các tình huống trong đó máy phát điện được sử dụng đúng
đi bởi một chức năng bao quanh. Biểu thức trình tạo nhỏ gọn hơn nhưng ít hơn
linh hoạt hơn so với các định nghĩa của trình tạo đầy đủ và có xu hướng thân thiện với bộ nhớ hơn
hơn so với cách hiểu danh sách tương đương.

Ví dụ:

 

& gt; & gt; & gt;

sum

(

i

*

i

cho

i

trong

range

(

10

))

# tổng bình phương

285

& gt; & gt; & gt;

xvec

=

[

10

,

20

,

30

]

& gt; & gt; & gt;

yvec

=

[

7

,

5

,

3

]

& gt; & gt; & gt;

sum

(

x

*

y

cho

x

,

y

trong

zip

(

xvec

,

yvec

< p class = "p">))

# chấm sản phẩm

260

& gt; & gt; & gt;

unique_words

=

set

(

từ

cho

dòng

trong

trang

cho

từ

in

line

.

chia nhỏ

< p class = "p"> ())

& gt; & gt; & gt;

thủ khoa

=

max

((

học sinh

.

gpa

,

học sinh

.

tên

)

dành cho

sinh viên

tham gia

sinh viên tốt nghiệp

)

& gt; & gt; & gt;

dữ liệu

=

'gôn'

& gt; & gt; & gt;

danh sách

(

dữ liệu

[

tôi

]

cho

i

trong

range

(

len

(

dữ liệu

)

< p class = "o"> -

1

,

-

1

,

-

1 < / p>

))

['f', 'l', 'o', 'g']

Chú thích cuối trang


Xem thêm những thông tin liên quan đến chủ đề python 3 lớp mới

Mind-bending metaclasses - adding function overloads to Python

  • Tác giả: mCoding
  • Ngày đăng: 2021-10-02
  • Đánh giá: 4 ⭐ ( 1896 lượt đánh giá )
  • Khớp với kết quả tìm kiếm: Metaclasses in Python allow you to customize the class creation process. We go over what metaclasses are and give some notable examples, including: abstract base classes, adding function overloads, and dataclasses or code generation.

    CONTEST WINNERS (CONTEST ENDED 10/9/21) :
    PyCharm: Yannick Kuhn, peter duffy
    CLion: BalkanSwine, Laurin Neff

    OFFICIAL CONTEST RULES:
    1. All entries must comply with the YouTube community guidelines ( http://www.youtube.com/t/community_guidelines) and YouTube Terms of Service (http://www.youtube.com/static?gl=US&template=terms). Entries that violate YouTube guidelines are automatically disqualified.
    2. YouTube is not a sponsor of the contest and viewers are required to release YouTube from any liability related to the contest.
    3. Privacy notice: no personal data will be collected for this contest.
    4. In order to enter, you must (a) be one of my subscribers, AND (b) make a top-level comment to the video including pycharm or clion or both. If you only include one you will only have a chance to win that corresponding license.
    5. The contest is free, there is no fee required to enter.
    6. Winners will be chosen randomly 1 week after the date the video went live from all users who have entered and not been disqualified.
    7. Each winner will be notified via a comment reply from me that details what prize was won (e.g. "Congratulations! You have won XYZ. Please email me."). I will ask the winner to contact me by email, and I will reply through email with a random token which must be posted as another reply to the winning comment from the winning account in order to verify account ownership and prevent fraud.
    8. Each winner will have 72 hours to respond AND prove account ownership or their prize is automatically forfeited and another winner will be chosen.
    9. A winner can only win 1 prize per contest.
    10. The prize pool for this contest is: 2 licenses for PyCharm Professional ("Free 1-Year Personal Subscription") and 2 licenses for CLion ("Free 1-Year Personal Subscription"), which are products made by JetBrains. A prize consists of 1 license, which will be delivered in the form of a redeemable code that can be redeemed at https://www.jetbrains.com/store/redeem/ before May 01, 2022.
    11. You may not enter the contest if doing so would be a violation of any relevant federal, state, and local laws, rules, and regulations, including U.S. sanctions.

    ― mCoding with James Murphy (https://mcoding.io)

    Source code: https://github.com/mCodingLLC/VideosSampleCode
    Python metaclass docs: https://docs.python.org/3/reference/datamodel.htmlmetaclasses
    Previous video on new: https://www.youtube.com/watch?v=-zsV0_QrfTw
    Another great metaprogramming video: https://www.youtube.com/watch?v=sPiWg5jSoZI
    Python descriptor docs: https://docs.python.org/3/howto/descriptor.html
    Python ABC docs: https://docs.python.org/3/library/abc.html

    AFFILIATES AND REFERRALS
    ---------------------------------------------------
    Automatically Improve Python Code Quality: https://sourcery.ai/?utm_source=YouTube&utm_campaign=mcoding&utm_medium=aff

    SUPPORT ME ⭐
    ---------------------------------------------------
    Sign up on Patreon to get your donor role and early access to videos!
    https://patreon.com/mCoding

    Feeling generous but don't have a Patreon? Donate via PayPal! (No sign up needed.)
    https://www.paypal.com/donate/?hosted_button_id=VJY5SLZ8BJHEE

    Want to donate crypto? Check out the rest of my supported donations on my website!
    https://mcoding.io/donate

    Top patrons and donors: Jameson, Laura M, John Martin, Dragos C, Vahnekie, Pieter G, Casey G, Sigmanificient

    BE ACTIVE IN MY COMMUNITY 😄
    ---------------------------------------------------
    Discord: https://discord.gg/Ye9yJtZQuN
    Github: https://github.com/mCodingLLC/
    Reddit: https://www.reddit.com/r/mCoding/
    Facebook: https://www.facebook.com/james.mcoding

    CHAPTERS
    ---------------------------------------------------
    0:00 Intro
    1:28 What is a metaclass
    3:58 Simplest possible metaclass
    4:59 Load time metaclass
    6:08 Abstract base classes
    8:03 Function overloads
    14:10 Dataclass code generation
    15:01 Giveaway instructions

Học lập trình Python — PyMI.vn

  • Tác giả: pymi.vn
  • Đánh giá: 4 ⭐ ( 5519 lượt đánh giá )
  • Khớp với kết quả tìm kiếm: Học lập trình Python chất lượng số 1 Việt Nam 2021 - đào tạo học viên từ không biết gì thành lập trình viên chuyên nghiệp. Đã đào tạo hơn 1000 lập trình viên sau 35 khóa học trên cả nước.

Hướng dẫn lập trình Python cho người mới bắt đầu

  • Tác giả: openplanning.net
  • Đánh giá: 4 ⭐ ( 1267 lượt đánh giá )
  • Khớp với kết quả tìm kiếm:

Học Python cơ bản và nâng cao - Học ngôn ngữ lập trình Python hay nhất

  • Tác giả: vietjack.com
  • Đánh giá: 4 ⭐ ( 1093 lượt đánh giá )
  • Khớp với kết quả tìm kiếm: Học Python cơ bản và nâng cao - Học ngôn ngữ lập trình Python hay nhất - Học Python cơ bản và nâng cao theo các bước đơn giản từ Tổng quan, Cài đặt, Biến, Toán tử, Cú pháp cơ bản, Hướng đối tượng, Vòng lặp, Chuỗi, Number, List, Dictionary, Tuple, Module, Xử lý ngoại lệ, Tool, Exception Handling, Socket, GUI, Multithread, Lập trình mạng, Xử lý XML.

Python 3.10 và những tính năng mới tuyệt vời

  • Tác giả: irender.vn
  • Đánh giá: 5 ⭐ ( 6877 lượt đánh giá )
  • Khớp với kết quả tìm kiếm: Với bản phát hành mới Python 3.10, PSF lại bổ sung thêm các tính năng mới đáng kinh ngạc giúp ngôn ngữ này viết hiệu quả hơn và dễ học hơn.

Ngôn ngữ lập trình cơ bản

  • Tác giả: download.com.vn
  • Đánh giá: 3 ⭐ ( 8943 lượt đánh giá )
  • Khớp với kết quả tìm kiếm: Python, Python 3.10.4 là ngôn ngữ lập trình hướng đối tượng động, có thể dùng để phát triển nhiều loại phần mềm khác nhau. Tải Python miễn phí.

Giáo trình Python PDF bản update mới nhất (Cập nhật 2021)

  • Tác giả: codegym.vn
  • Đánh giá: 4 ⭐ ( 2085 lượt đánh giá )
  • Khớp với kết quả tìm kiếm: Tải xuống bộ giáo trình Python PDF cực kỳ chất lượng bản update mới nhất dành cho những người mới bắt đầu tìm hiểu...

Xem thêm các bài viết khác thuộc chuyên mục: Kiến thức lập trình

Xem Thêm  129 sắc thái của màu hồng với tên, mã Hex, RGB, CMYK - mã màu hex màu hồng

By ads_php