Hướng dẫn can modules have variables python? - mô-đun có thể có biến python không?

Đây là những gì đang diễn ra.

Show

Đầu tiên, các biến toàn cầu duy nhất Python thực sự có là các biến số lượng mô-đun. Bạn không thể tạo ra một biến thực sự toàn cầu; Tất cả những gì bạn có thể làm là tạo một biến trong một phạm vi cụ thể. .

Tất cả bạn phải làm để tạo một biến toàn cầu mô-đun chỉ là gán cho một tên.

Hãy tưởng tượng một tệp được gọi là foo.py, chứa dòng đơn này:

X = 1

Bây giờ hãy tưởng tượng bạn nhập nó.

import foo
print(foo.X)  # prints 1

Tuy nhiên, giả sử bạn muốn sử dụng một trong các biến phạm vi mô-đun của mình như một toàn cầu bên trong một hàm, như trong ví dụ của bạn. Mặc định của Python là giả định rằng các biến hàm là cục bộ. Bạn chỉ cần thêm khai báo

import foo
print(foo.X)  # prints 1
07 trong chức năng của mình, trước khi bạn cố gắng sử dụng toàn cầu.

def initDB(name):
    global __DBNAME__  # add this line!
    if __DBNAME__ is None: # see notes below; explicit test for None
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")

Nhân tiện, trong ví dụ này, thử nghiệm

import foo
print(foo.X)  # prints 1
08 đơn giản là đủ, bởi vì bất kỳ giá trị chuỗi nào khác ngoài một chuỗi trống sẽ đánh giá đúng, do đó, bất kỳ tên cơ sở dữ liệu thực tế nào cũng sẽ đánh giá đúng. Nhưng đối với các biến có thể chứa một giá trị số có thể là 0, bạn không thể nói
import foo
print(foo.X)  # prints 1
09; Trong trường hợp đó, bạn nên kiểm tra rõ ràng
import foo
print(foo.X)  # prints 1
10 bằng toán tử
import foo
print(foo.X)  # prints 1
11. Tôi đã sửa đổi ví dụ để thêm một bài kiểm tra
import foo
print(foo.X)  # prints 1
10 rõ ràng. Bài kiểm tra rõ ràng cho
import foo
print(foo.X)  # prints 1
10 không bao giờ sai, vì vậy tôi mặc định sử dụng nó.

Cuối cùng, như những người khác đã lưu ý trên trang này, hai tín hiệu nhấn mạnh hàng đầu cho Python rằng bạn muốn biến là "riêng tư" cho mô -đun. Nếu bạn từng làm

import foo
print(foo.X)  # prints 1
14, Python sẽ không nhập tên với hai dấu gạch dưới hàng đầu vào không gian tên của bạn. Nhưng nếu bạn chỉ thực hiện một
import foo
print(foo.X)  # prints 1
15 đơn giản và sau đó nói
import foo
print(foo.X)  # prints 1
16, bạn sẽ thấy các biến "riêng tư" trong danh sách và nếu bạn đề cập rõ ràng đến
import foo
print(foo.X)  # prints 1
17 Python sẽ không quan tâm, nó sẽ chỉ cho phép bạn đề cập đến nó. Các dấu gạch dưới hàng đầu là một manh mối chính cho người dùng mô -đun của bạn mà bạn không muốn họ sửa đổi tên đó theo một số giá trị của riêng họ.

Nó được coi là thực tiễn tốt nhất trong Python không phải làm

import foo
print(foo.X)  # prints 1
18, mà là để giảm thiểu sự kết hợp và tối đa hóa tính rõ ràng bằng cách sử dụng
import foo
print(foo.X)  # prints 1
19 hoặc bằng cách thực hiện một cách rõ ràng khi nhập như
import foo
print(foo.X)  # prints 1
20.

Chỉnh sửa: Nếu, vì một số lý do, bạn cần phải làm một cái gì đó như thế này trong một phiên bản Python rất cũ không có từ khóa

import foo
print(foo.X)  # prints 1
07, có một cách giải quyết dễ dàng. Thay vì đặt một biến toàn cầu mô -đun trực tiếp, hãy sử dụng loại có thể thay đổi ở cấp độ toàn cầu mô -đun và lưu trữ các giá trị của bạn bên trong nó.

Trong các chức năng của bạn, tên biến toàn cầu sẽ chỉ được đọc; Bạn sẽ không thể viết lại tên biến toàn cầu thực tế. .

Bạn có thể sử dụng

import foo
print(foo.X)  # prints 1
22 nhưng mã của bạn sẽ xấu xí:

__DBNAME__ = [None] # use length-1 list as a mutable

# later, in code:  
if __DBNAME__[0] is None:
    __DBNAME__[0] = name

A

import foo
print(foo.X)  # prints 1
23 là tốt hơn. Nhưng thuận tiện nhất là một thể hiện lớp và bạn chỉ có thể sử dụng một lớp tầm thường:

class Box:
    pass

__m = Box()  # m will contain all module-level values
__m.dbname = None  # database name global in module

# later, in code:
if __m.dbname is None:
    __m.dbname = name

(Bạn không thực sự cần tận dụng biến tên cơ sở dữ liệu.)

Tôi thích đường cú pháp chỉ sử dụng

import foo
print(foo.X)  # prints 1
24 chứ không phải
import foo
print(foo.X)  # prints 1
25; Có vẻ như giải pháp thuận tiện nhất theo ý kiến ​​của tôi. Nhưng giải pháp
import foo
print(foo.X)  # prints 1
23 cũng hoạt động tốt.

Với

import foo
print(foo.X)  # prints 1
23, bạn có thể sử dụng bất kỳ giá trị băm nào làm khóa, nhưng khi bạn hài lòng với các tên định danh hợp lệ, bạn có thể sử dụng một lớp tầm thường như
import foo
print(foo.X)  # prints 1
28 ở trên.

Câu hỏi chung¶

Có trình gỡ lỗi cấp mã nguồn với các điểm dừng, một bước, v.v ...

Yes.

Một số trình gỡ lỗi cho Python được mô tả dưới đây và chức năng tích hợp

import foo
print(foo.X)  # prints 1
29 cho phép bạn rơi vào bất kỳ trong số chúng.

Mô-đun PDB là một trình gỡ lỗi chế độ điều khiển đơn giản nhưng đầy đủ cho Python. Nó là một phần của thư viện Python tiêu chuẩn và là

import foo
print(foo.X)  # prints 1
30. Bạn cũng có thể viết trình gỡ lỗi của riêng mình bằng cách sử dụng mã cho PDB làm ví dụ.

Môi trường phát triển tương tác nhàn rỗi, là một phần của phân phối Python tiêu chuẩn (thường có sẵn dưới dạng công cụ/tập lệnh/nhàn rỗi), bao gồm trình gỡ lỗi đồ họa.

Pythonwin là một IDE Python bao gồm một trình gỡ lỗi GUI dựa trên PDB. Các điểm dừng màu sắc của Pythonwin và có khá nhiều tính năng thú vị như gỡ lỗi các chương trình phi Pythonwin. Pythonwin có sẵn như là một phần của Dự án PyWin32 và là một phần của phân phối ActivePython.

Eric là một IDE được xây dựng trên PYQT và thành phần chỉnh sửa Scintilla.

Trepan3K là một trình gỡ lỗi giống như GDB.

Visual Studio Code là một IDE với các công cụ gỡ lỗi tích hợp với phần mềm kiểm soát phiên bản.

Có một số IDE Python thương mại bao gồm các trình gỡ lỗi đồ họa. Chúng bao gồm:

  • Cánh ide

  • Komodo ide

  • Pycharm

Có công cụ nào giúp tìm lỗi hoặc thực hiện phân tích tĩnh không? ¶

Yes.

Pylint và Pyflakes kiểm tra cơ bản sẽ giúp bạn bắt lỗi sớm hơn.

Các trình kiểm tra loại tĩnh như mypy, pyre và pytype có thể kiểm tra các gợi ý loại trong mã nguồn python.

Làm thế nào tôi có thể tạo một nhị phân độc lập từ kịch bản Python? ¶

Bạn không cần khả năng biên dịch mã Python với C nếu tất cả những gì bạn muốn là một chương trình độc lập mà người dùng có thể tải xuống và chạy mà không phải cài đặt phân phối Python trước. Có một số công cụ xác định tập hợp các mô -đun theo yêu cầu của một chương trình và liên kết các mô -đun này cùng với một nhị phân Python để tạo ra một thực thi duy nhất.

Một là sử dụng công cụ đóng băng, được bao gồm trong cây nguồn Python là

import foo
print(foo.X)  # prints 1
31. Nó chuyển đổi mã byte python thành m mảng C; Với trình biên dịch C, bạn có thể nhúng tất cả các mô -đun của mình vào một chương trình mới, sau đó được liên kết với các mô -đun Python tiêu chuẩn.

Nó hoạt động bằng cách quét nguồn của bạn một cách đệ quy cho các câu lệnh nhập (ở cả hai dạng) và tìm kiếm các mô-đun trong đường dẫn Python tiêu chuẩn cũng như trong thư mục nguồn (cho các mô-đun tích hợp). Sau đó, nó biến mã byte cho các mô-đun được viết bằng python thành mã C (các bộ khởi tạo mảng có thể được chuyển thành các đối tượng mã bằng mô-đun Nguyên soái) và tạo tệp cấu hình tùy chỉnh chỉ chứa các mô-đun tích hợp đó thực sự được sử dụng trong chương trình. Sau đó, nó biên dịch mã C được tạo và liên kết nó với phần còn lại của trình thông dịch Python để tạo thành một nhị phân khép kín hoạt động giống hệt như tập lệnh của bạn.

Các gói sau đây có thể giúp tạo ra bảng điều khiển và thực thi GUI:

  • Nuitka (đa nền tảng)

  • Pyinstaller (đa nền tảng)

  • Pyoxidizer (đa nền tảng)

  • CX_Freeze (đa nền tảng)

  • PY2App (chỉ có macOS)

  • py2exe (chỉ Windows)

Có tiêu chuẩn mã hóa hoặc hướng dẫn phong cách cho các chương trình Python không? ¶

Đúng. Kiểu mã hóa cần thiết cho các mô -đun thư viện tiêu chuẩn được ghi nhận là PEP 8.PEP 8.

Ngôn ngữ cốt lõi

Tại sao tôi lại nhận được không liên lạc khi biến có giá trị? ¶

Có thể là một bất ngờ khi có được sự không liên kết trong mã làm việc trước đó khi nó được sửa đổi bằng cách thêm một câu lệnh gán ở đâu đó trong phần thân của một hàm.

Mã này:

>>> x = 10
>>> def bar():
...     print(x)
>>> bar()
10

hoạt động, nhưng mã này:

>>> x = 10
>>> def foo():
...     print(x)
...     x += 1

dẫn đến một sự không liên kết:

>>> foo()
Traceback (most recent call last):
  ...
UnboundLocalError: local variable 'x' referenced before assignment

Điều này là do khi bạn thực hiện một gán cho một biến trong một phạm vi, biến đó trở thành cục bộ với phạm vi đó và bóng tối bất kỳ biến có tên tương tự nào trong phạm vi bên ngoài. Vì câu lệnh cuối cùng trong FOO gán một giá trị mới cho

import foo
print(foo.X)  # prints 1
32, trình biên dịch nhận ra nó là một biến cục bộ. Do đó, khi
import foo
print(foo.X)  # prints 1
33 sớm hơn cố gắng in biến cục bộ không được hưởng và kết quả lỗi.

Trong ví dụ trên, bạn có thể truy cập biến phạm vi bên ngoài bằng cách khai báo nó toàn cầu:

>>> x = 10
>>> def foobar():
...     global x
...     print(x)
...     x += 1
>>> foobar()
10

Tuyên bố rõ ràng này được yêu cầu để nhắc nhở bạn rằng (không giống như tình huống tương tự bề ngoài với các biến lớp và phiên bản), bạn thực sự đang sửa đổi giá trị của biến trong phạm vi bên ngoài:

Bạn có thể làm một điều tương tự trong phạm vi lồng nhau bằng cách sử dụng từ khóa

import foo
print(foo.X)  # prints 1
34:

>>> def foo():
...    x = 10
...    def bar():
...        nonlocal x
...        print(x)
...        x += 1
...    bar()
...    print(x)
>>> foo()
10
11

Các quy tắc cho các biến địa phương và toàn cầu trong Python là gì? ¶

Trong Python, các biến chỉ được tham chiếu bên trong một hàm là toàn cầu ngầm. Nếu một biến được gán một giá trị ở bất cứ đâu trong cơ thể chức năng, thì nó được coi là địa phương trừ khi được tuyên bố rõ ràng là toàn cầu.

Mặc dù lúc đầu một chút đáng ngạc nhiên, nhưng một khoảnh khắc xem xét điều này. Một mặt, yêu cầu

import foo
print(foo.X)  # prints 1
35 cho các biến được chỉ định cung cấp một thanh chống lại các tác dụng phụ ngoài ý muốn. Mặt khác, nếu
import foo
print(foo.X)  # prints 1
35 được yêu cầu cho tất cả các tài liệu tham khảo toàn cầu, bạn sẽ sử dụng
import foo
print(foo.X)  # prints 1
35 mọi lúc. Bạn phải tuyên bố là toàn cầu mọi tham chiếu đến hàm tích hợp hoặc thành phần của mô-đun nhập khẩu. Sự lộn xộn này sẽ đánh bại tính hữu ích của Tuyên bố
import foo
print(foo.X)  # prints 1
35 để xác định các tác dụng phụ.

Tại sao Lambdas được xác định trong một vòng lặp với các giá trị khác nhau đều trả về cùng một kết quả? ¶

Giả sử bạn sử dụng một vòng lặp để xác định một vài lambdas khác nhau (hoặc thậm chí các hàm đơn giản), ví dụ:

import foo
print(foo.X)  # prints 1
0

Điều này cung cấp cho bạn một danh sách chứa 5 lambdas tính toán

import foo
print(foo.X)  # prints 1
39. Bạn có thể mong đợi rằng, khi được gọi, họ sẽ trở lại, tương ứng,
import foo
print(foo.X)  # prints 1
40,
import foo
print(foo.X)  # prints 1
41,
import foo
print(foo.X)  # prints 1
42,
import foo
print(foo.X)  # prints 1
43 và
import foo
print(foo.X)  # prints 1
44. Tuy nhiên, khi bạn thực sự thử, bạn sẽ thấy rằng tất cả họ trở lại
import foo
print(foo.X)  # prints 1
44:

import foo
print(foo.X)  # prints 1
1

Điều này xảy ra bởi vì

import foo
print(foo.X)  # prints 1
32 không phải là cục bộ với Lambdas, nhưng được xác định trong phạm vi bên ngoài và nó được truy cập khi Lambda được gọi - không phải khi nó được xác định. Vào cuối vòng lặp, giá trị của
import foo
print(foo.X)  # prints 1
32 là
import foo
print(foo.X)  # prints 1
42, vì vậy tất cả các chức năng hiện trả về
import foo
print(foo.X)  # prints 1
49, tức là
import foo
print(foo.X)  # prints 1
44. Bạn cũng có thể xác minh điều này bằng cách thay đổi giá trị của
import foo
print(foo.X)  # prints 1
32 và xem kết quả của Lambdas thay đổi như thế nào:

import foo
print(foo.X)  # prints 1
2

Để tránh điều này, bạn cần lưu các giá trị trong các biến cục bộ vào lambdas, để chúng không dựa vào giá trị của toàn cầu

import foo
print(foo.X)  # prints 1
32:

import foo
print(foo.X)  # prints 1
3

Ở đây,

import foo
print(foo.X)  # prints 1
53 tạo ra một biến mới
import foo
print(foo.X)  # prints 1
54 cục bộ cho Lambda và được tính toán khi Lambda được xác định sao cho nó có cùng giá trị mà
import foo
print(foo.X)  # prints 1
32 có tại thời điểm đó trong vòng lặp. Điều này có nghĩa là giá trị của
import foo
print(foo.X)  # prints 1
54 sẽ là
import foo
print(foo.X)  # prints 1
40 trong Lambda đầu tiên,
import foo
print(foo.X)  # prints 1
41 trong lần thứ hai,
import foo
print(foo.X)  # prints 1
59 trong phần ba, v.v. Do đó, mỗi lambda bây giờ sẽ trả về kết quả chính xác:

import foo
print(foo.X)  # prints 1
4

Lưu ý rằng hành vi này không đặc biệt đối với Lambdas, nhưng cũng áp dụng cho các chức năng thường xuyên.

Làm cách nào để chia sẻ các biến toàn cầu trên các mô -đun? ¶

Cách kinh điển để chia sẻ thông tin trên các mô -đun trong một chương trình là tạo một mô -đun đặc biệt (thường được gọi là Cấu hình hoặc CFG). Chỉ cần nhập mô -đun cấu hình trong tất cả các mô -đun trong ứng dụng của bạn; Các mô -đun sau đó trở thành có sẵn như một tên toàn cầu. Bởi vì chỉ có một trường hợp của mỗi mô -đun, bất kỳ thay đổi nào được thực hiện đối với đối tượng mô -đun được phản ánh ở mọi nơi. Ví dụ:

config.py:

import foo
print(foo.X)  # prints 1
5

mod.py:

import foo
print(foo.X)  # prints 1
6

main.py:

import foo
print(foo.X)  # prints 1
7

Lưu ý rằng sử dụng một mô -đun cũng là cơ sở để thực hiện mẫu thiết kế Singleton, vì lý do tương tự.

Các thực tiễn tốt nhất của người Viking là gì để sử dụng nhập khẩu trong một mô -đun là gì? ¶

Nói chung, don lồng sử dụng

import foo
print(foo.X)  # prints 1
60. Làm như vậy củng cố không gian tên của nhà nhập khẩu, và làm cho các linters khó phát hiện các tên không xác định hơn nhiều.

Nhập các mô -đun ở đầu một tập tin. Làm như vậy làm rõ những mô -đun khác mà mã của bạn yêu cầu và tránh các câu hỏi về việc tên mô -đun có nằm trong phạm vi hay không. Sử dụng một lần nhập trên mỗi dòng giúp dễ dàng thêm và xóa nhập mô -đun, nhưng sử dụng nhiều lần nhập mỗi dòng sử dụng ít không gian màn hình hơn.

Nó thực hành tốt nếu bạn nhập các mô -đun theo thứ tự sau:

  1. Các mô -đun thư viện tiêu chuẩn - ví dụ:

    import foo
    print(foo.X)  # prints 1
    
    61,
    import foo
    print(foo.X)  # prints 1
    
    62,
    import foo
    print(foo.X)  # prints 1
    
    63,
    import foo
    print(foo.X)  # prints 1
    
    64

  2. Các mô-đun thư viện của bên thứ ba (bất cứ điều gì được cài đặt trong thư mục gói trang web Python)-ví dụ: MX.DATETIME, ZODB, PIL.IMAGE, ETC.

  3. Các mô -đun phát triển cục bộ

Đôi khi cần phải di chuyển nhập khẩu vào một chức năng hoặc lớp để tránh các vấn đề với nhập khẩu tròn. Gordon McMillan nói:

Nhập khẩu tròn là tốt trong đó cả hai mô -đun đều sử dụng hình thức nhập khẩu nhập khẩu. Họ thất bại khi mô -đun thứ 2 muốn lấy một cái tên trong số đầu tiên (từ tên nhập mô -đun tên) và nhập ở cấp cao nhất. Đó là vì tên trong phần 1 chưa có sẵn, bởi vì mô -đun đầu tiên đang bận nhập vào thứ 2.

Trong trường hợp này, nếu mô -đun thứ hai chỉ được sử dụng trong một chức năng, thì việc nhập có thể dễ dàng được chuyển vào hàm đó. Vào thời điểm nhập được gọi, mô -đun đầu tiên sẽ hoàn thành khởi tạo và mô -đun thứ hai có thể thực hiện nhập.

Cũng có thể cần thiết để chuyển nhập ra khỏi cấp mã cao nhất nếu một số mô-đun là dành riêng cho nền tảng. Trong trường hợp đó, thậm chí có thể không thể nhập tất cả các mô -đun ở đầu tệp. Trong trường hợp này, nhập các mô-đun chính xác trong mã dành riêng cho nền tảng tương ứng là một tùy chọn tốt.

Chỉ di chuyển nhập vào một phạm vi cục bộ, chẳng hạn như bên trong định nghĩa hàm, nếu nó cần thiết để giải quyết một vấn đề như tránh nhập vòng tròn hoặc đang cố gắng giảm thời gian khởi tạo của một mô -đun. Kỹ thuật này đặc biệt hữu ích nếu nhiều người nhập khẩu là không cần thiết tùy thuộc vào cách chương trình thực hiện. Bạn cũng có thể muốn di chuyển nhập vào một hàm nếu các mô -đun chỉ được sử dụng trong hàm đó. Lưu ý rằng việc tải mô -đun lần đầu tiên có thể tốn kém do khởi tạo một lần của mô -đun, nhưng tải một mô -đun nhiều lần là hầu như miễn phí, chỉ tốn một vài lần tra cứu từ điển. Ngay cả khi tên mô -đun đã ra khỏi phạm vi, mô -đun có thể có sẵn trong

import foo
print(foo.X)  # prints 1
65.

Tại sao các giá trị mặc định được chia sẻ giữa các đối tượng? ¶

Loại lỗi này thường cắn các lập trình viên neophyte. Xem xét chức năng này:

import foo
print(foo.X)  # prints 1
8

Lần đầu tiên bạn gọi chức năng này,

import foo
print(foo.X)  # prints 1
66 chứa một mục. Lần thứ hai,
import foo
print(foo.X)  # prints 1
66 chứa hai mục vì khi
import foo
print(foo.X)  # prints 1
68 bắt đầu thực thi,
import foo
print(foo.X)  # prints 1
66 bắt đầu với một mục đã có trong đó.

Người ta thường hy vọng rằng một cuộc gọi hàm tạo ra các đối tượng mới cho các giá trị mặc định. Đây không phải là những gì xảy ra. Các giá trị mặc định được tạo chính xác một lần, khi hàm được xác định. Nếu đối tượng đó được thay đổi, giống như từ điển trong ví dụ này, các cuộc gọi tiếp theo đến hàm sẽ đề cập đến đối tượng đã thay đổi này.

Theo định nghĩa, các đối tượng bất biến như số, chuỗi, bộ dữ liệu và

import foo
print(foo.X)  # prints 1
70, an toàn khỏi sự thay đổi. Các thay đổi đối với các đối tượng có thể thay đổi như từ điển, danh sách và các trường hợp lớp có thể dẫn đến sự nhầm lẫn.

Do tính năng này, thực tế lập trình tốt là không sử dụng các đối tượng có thể thay đổi làm giá trị mặc định. Thay vào đó, hãy sử dụng

import foo
print(foo.X)  # prints 1
70 làm giá trị mặc định và bên trong hàm, hãy kiểm tra xem tham số là
import foo
print(foo.X)  # prints 1
70 và tạo danh sách/từ điển mới/bất cứ điều gì nếu nó là. Ví dụ, don lồng viết:

but:

import foo
print(foo.X)  # prints 1
9

Tính năng này có thể hữu ích. Khi bạn có một hàm tốn thời gian để tính toán, một kỹ thuật phổ biến là lưu trữ các tham số và giá trị kết quả của mỗi cuộc gọi cho hàm và trả lại giá trị được lưu trữ nếu cùng một giá trị được yêu cầu. Đây được gọi là ghi nhớ của người Hồi giáo, và có thể được thực hiện như thế này:

def initDB(name):
    global __DBNAME__  # add this line!
    if __DBNAME__ is None: # see notes below; explicit test for None
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")
0

Bạn có thể sử dụng biến toàn cầu chứa từ điển thay vì giá trị mặc định; Nó là một vấn đề của hương vị.

Làm cách nào để chuyển các tham số từ khóa hoặc tùy chọn từ hàm này sang chức năng khác? ¶

Thu thập các đối số bằng cách sử dụng các nhà xác định

import foo
print(foo.X)  # prints 1
73 và
import foo
print(foo.X)  # prints 1
74 trong danh sách tham số chức năng; Điều này cung cấp cho bạn các đối số vị trí như một tuple và từ khóa đối số như một từ điển. Sau đó, bạn có thể chuyển các đối số này khi gọi một chức năng khác bằng cách sử dụng
import foo
print(foo.X)  # prints 1
73 và
import foo
print(foo.X)  # prints 1
74:

def initDB(name):
    global __DBNAME__  # add this line!
    if __DBNAME__ is None: # see notes below; explicit test for None
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")
1

Sự khác biệt giữa các đối số và tham số là gì? ¶

Các tham số được xác định bởi các tên xuất hiện trong một định nghĩa hàm, trong khi các đối số là các giá trị thực sự được truyền đến một hàm khi gọi nó. Các tham số xác định loại đối số mà một hàm có thể chấp nhận. Ví dụ, đưa ra định nghĩa chức năng: are defined by the names that appear in a function definition, whereas arguments are the values actually passed to a function when calling it. Parameters define what kind of arguments a function can accept. For example, given the function definition:

def initDB(name):
    global __DBNAME__  # add this line!
    if __DBNAME__ is None: # see notes below; explicit test for None
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")
2

FOO, Bar và Kwargs là các tham số của

import foo
print(foo.X)  # prints 1
77. Tuy nhiên, khi gọi
import foo
print(foo.X)  # prints 1
77, ví dụ:

def initDB(name):
    global __DBNAME__  # add this line!
    if __DBNAME__ is None: # see notes below; explicit test for None
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")
3

Các giá trị

import foo
print(foo.X)  # prints 1
79,
import foo
print(foo.X)  # prints 1
80 và
import foo
print(foo.X)  # prints 1
81 là các đối số.

Tại sao thay đổi danh sách ‘Y, cũng thay đổi danh sách‘ X,? ¶

Nếu bạn đã viết mã như:

def initDB(name):
    global __DBNAME__  # add this line!
    if __DBNAME__ is None: # see notes below; explicit test for None
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")
4

Bạn có thể tự hỏi tại sao lại thêm một yếu tố vào

import foo
print(foo.X)  # prints 1
82 đã thay đổi
import foo
print(foo.X)  # prints 1
32 quá.

Có hai yếu tố tạo ra kết quả này:

  1. Các biến chỉ đơn giản là tên đề cập đến các đối tượng. Thực hiện

    import foo
    print(foo.X)  # prints 1
    
    84 không tạo ra một bản sao của danh sách - nó tạo ra một biến mới
    import foo
    print(foo.X)  # prints 1
    
    82 đề cập đến cùng một đối tượng
    import foo
    print(foo.X)  # prints 1
    
    32 đề cập đến. Điều này có nghĩa là chỉ có một đối tượng (danh sách) và cả
    import foo
    print(foo.X)  # prints 1
    
    32 và
    import foo
    print(foo.X)  # prints 1
    
    82 đều đề cập đến nó.

  2. Danh sách có thể thay đổi, điều đó có nghĩa là bạn có thể thay đổi nội dung của họ.mutable, which means that you can change their content.

Sau cuộc gọi đến

import foo
print(foo.X)  # prints 1
89, nội dung của đối tượng có thể thay đổi đã thay đổi từ
import foo
print(foo.X)  # prints 1
90 thành
import foo
print(foo.X)  # prints 1
91. Vì cả hai biến đề cập đến cùng một đối tượng, sử dụng tên sẽ truy cập giá trị đã sửa đổi
import foo
print(foo.X)  # prints 1
91.

Thay vào đó, nếu chúng ta gán một đối tượng bất biến cho

import foo
print(foo.X)  # prints 1
32:

def initDB(name):
    global __DBNAME__  # add this line!
    if __DBNAME__ is None: # see notes below; explicit test for None
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")
5

Chúng ta có thể thấy rằng trong trường hợp này

import foo
print(foo.X)  # prints 1
32 và
import foo
print(foo.X)  # prints 1
82 không còn bằng nhau nữa. Điều này là do các số nguyên là bất biến và khi chúng ta làm
import foo
print(foo.X)  # prints 1
96, chúng ta không biến đổi int
import foo
print(foo.X)  # prints 1
97 bằng cách tăng giá trị của nó; Thay vào đó, chúng tôi đang tạo một đối tượng mới (int
import foo
print(foo.X)  # prints 1
98) và gán nó cho
import foo
print(foo.X)  # prints 1
32 (nghĩa là thay đổi đối tượng nào
import foo
print(foo.X)  # prints 1
32 đề cập đến). Sau nhiệm vụ này, chúng tôi có hai đối tượng (INTS
import foo
print(foo.X)  # prints 1
98 và
import foo
print(foo.X)  # prints 1
97) và hai biến đề cập đến chúng (
import foo
print(foo.X)  # prints 1
32 hiện đề cập đến
import foo
print(foo.X)  # prints 1
98 nhưng
import foo
print(foo.X)  # prints 1
82 vẫn đề cập đến
import foo
print(foo.X)  # prints 1
97).immutable, and when we do
import foo
print(foo.X)  # prints 1
96 we are not mutating the int
import foo
print(foo.X)  # prints 1
97 by incrementing its value; instead, we are creating a new object (the int
import foo
print(foo.X)  # prints 1
98) and assigning it to
import foo
print(foo.X)  # prints 1
32 (that is, changing which object
import foo
print(foo.X)  # prints 1
32 refers to). After this assignment we have two objects (the ints
import foo
print(foo.X)  # prints 1
98 and
import foo
print(foo.X)  # prints 1
97) and two variables that refer to them (
import foo
print(foo.X)  # prints 1
32 now refers to
import foo
print(foo.X)  # prints 1
98 but
import foo
print(foo.X)  # prints 1
82 still refers to
import foo
print(foo.X)  # prints 1
97).

Một số hoạt động (ví dụ

def initDB(name):
    global __DBNAME__  # add this line!
    if __DBNAME__ is None: # see notes below; explicit test for None
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")
07 và
def initDB(name):
    global __DBNAME__  # add this line!
    if __DBNAME__ is None: # see notes below; explicit test for None
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")
08) làm biến đổi đối tượng, trong khi các hoạt động tương tự bề ngoài (ví dụ
def initDB(name):
    global __DBNAME__  # add this line!
    if __DBNAME__ is None: # see notes below; explicit test for None
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")
09 và
def initDB(name):
    global __DBNAME__  # add this line!
    if __DBNAME__ is None: # see notes below; explicit test for None
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")
10) tạo ra một đối tượng mới. Nói chung trong Python (và trong tất cả các trường hợp trong thư viện tiêu chuẩn), một phương thức làm đột biến một đối tượng sẽ trả về
import foo
print(foo.X)  # prints 1
70 để giúp tránh hai loại hoạt động bị nhầm lẫn. Vì vậy, nếu bạn viết nhầm
def initDB(name):
    global __DBNAME__  # add this line!
    if __DBNAME__ is None: # see notes below; explicit test for None
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")
08 nghĩ rằng nó sẽ cung cấp cho bạn một bản sao được sắp xếp của
import foo
print(foo.X)  # prints 1
82, bạn sẽ kết thúc với
import foo
print(foo.X)  # prints 1
70, điều này có thể sẽ khiến chương trình của bạn tạo ra lỗi dễ chẩn đoán dễ dàng.

Tuy nhiên, có một lớp hoạt động trong đó cùng một hoạt động đôi khi có các hành vi khác nhau với các loại khác nhau: các toán tử phân công tăng cường. Ví dụ,

def initDB(name):
    global __DBNAME__  # add this line!
    if __DBNAME__ is None: # see notes below; explicit test for None
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")
15 đột biến danh sách nhưng không phải là bộ dữ liệu hoặc INT (
def initDB(name):
    global __DBNAME__  # add this line!
    if __DBNAME__ is None: # see notes below; explicit test for None
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")
16 tương đương với
def initDB(name):
    global __DBNAME__  # add this line!
    if __DBNAME__ is None: # see notes below; explicit test for None
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")
17 và đột biến
def initDB(name):
    global __DBNAME__  # add this line!
    if __DBNAME__ is None: # see notes below; explicit test for None
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")
18, trong khi
def initDB(name):
    global __DBNAME__  # add this line!
    if __DBNAME__ is None: # see notes below; explicit test for None
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")
19 và
def initDB(name):
    global __DBNAME__  # add this line!
    if __DBNAME__ is None: # see notes below; explicit test for None
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")
20 tạo ra các đối tượng mới).

Nói cách khác:

  • Nếu chúng ta có một đối tượng có thể thay đổi (

    def initDB(name):
        global __DBNAME__  # add this line!
        if __DBNAME__ is None: # see notes below; explicit test for None
            __DBNAME__ = name
        else:
            raise RuntimeError("Database name has already been set.")
    
    21,
    def initDB(name):
        global __DBNAME__  # add this line!
        if __DBNAME__ is None: # see notes below; explicit test for None
            __DBNAME__ = name
        else:
            raise RuntimeError("Database name has already been set.")
    
    22,
    def initDB(name):
        global __DBNAME__  # add this line!
        if __DBNAME__ is None: # see notes below; explicit test for None
            __DBNAME__ = name
        else:
            raise RuntimeError("Database name has already been set.")
    
    23, v.v.), chúng ta có thể sử dụng một số hoạt động cụ thể để biến đổi nó và tất cả các biến đề cập đến nó sẽ thấy sự thay đổi.

  • Nếu chúng ta có một đối tượng bất biến (

    def initDB(name):
        global __DBNAME__  # add this line!
        if __DBNAME__ is None: # see notes below; explicit test for None
            __DBNAME__ = name
        else:
            raise RuntimeError("Database name has already been set.")
    
    24,
    def initDB(name):
        global __DBNAME__  # add this line!
        if __DBNAME__ is None: # see notes below; explicit test for None
            __DBNAME__ = name
        else:
            raise RuntimeError("Database name has already been set.")
    
    25,
    def initDB(name):
        global __DBNAME__  # add this line!
        if __DBNAME__ is None: # see notes below; explicit test for None
            __DBNAME__ = name
        else:
            raise RuntimeError("Database name has already been set.")
    
    26, v.v.), tất cả các biến đề cập đến nó sẽ luôn thấy cùng một giá trị, nhưng các hoạt động chuyển đổi giá trị đó thành một giá trị mới luôn trả về một đối tượng mới.

Nếu bạn muốn biết liệu hai biến có đề cập đến cùng một đối tượng hay không, bạn có thể sử dụng toán tử

def initDB(name):
    global __DBNAME__  # add this line!
    if __DBNAME__ is None: # see notes below; explicit test for None
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")
27 hoặc hàm tích hợp
def initDB(name):
    global __DBNAME__  # add this line!
    if __DBNAME__ is None: # see notes below; explicit test for None
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")
28.

Làm cách nào để viết một hàm với các tham số đầu ra (gọi theo tham chiếu)? ¶

Hãy nhớ rằng các lập luận được thông qua bằng cách chuyển nhượng trong Python. Vì nhiệm vụ chỉ tạo ra các tham chiếu đến các đối tượng, nên không có bí danh nào giữa một tên đối số trong người gọi và callee, và do đó, không có tham chiếu nào. Bạn có thể đạt được hiệu ứng mong muốn theo một số cách.

  1. Bằng cách trả lại kết quả:

    def initDB(name):
        global __DBNAME__  # add this line!
        if __DBNAME__ is None: # see notes below; explicit test for None
            __DBNAME__ = name
        else:
            raise RuntimeError("Database name has already been set.")
    
    6

    Đây hầu như luôn luôn là giải pháp rõ ràng nhất.

  2. Bằng cách sử dụng các biến toàn cầu. Đây không phải là chủ đề an toàn, và không được khuyến khích.

  3. Bằng cách chuyển một đối tượng có thể thay đổi (thay đổi tại chỗ):

    def initDB(name):
        global __DBNAME__  # add this line!
        if __DBNAME__ is None: # see notes below; explicit test for None
            __DBNAME__ = name
        else:
            raise RuntimeError("Database name has already been set.")
    
    7

  4. Bằng cách truyền trong một từ điển bị đột biến:

    def initDB(name):
        global __DBNAME__  # add this line!
        if __DBNAME__ is None: # see notes below; explicit test for None
            __DBNAME__ = name
        else:
            raise RuntimeError("Database name has already been set.")
    
    8

  5. Hoặc gói các giá trị trong một thể hiện lớp:

    def initDB(name):
        global __DBNAME__  # add this line!
        if __DBNAME__ is None: # see notes below; explicit test for None
            __DBNAME__ = name
        else:
            raise RuntimeError("Database name has already been set.")
    
    9

    Có hầu như không bao giờ là một lý do chính đáng để có được điều này phức tạp.

Lựa chọn tốt nhất của bạn là trả về một tuple chứa nhiều kết quả.

Làm thế nào để bạn thực hiện một chức năng bậc cao hơn trong Python? ¶

Bạn có hai lựa chọn: Bạn có thể sử dụng phạm vi lồng nhau hoặc bạn có thể sử dụng các đối tượng có thể gọi được. Ví dụ: giả sử bạn muốn xác định

def initDB(name):
    global __DBNAME__  # add this line!
    if __DBNAME__ is None: # see notes below; explicit test for None
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")
29 trả về hàm
def initDB(name):
    global __DBNAME__  # add this line!
    if __DBNAME__ is None: # see notes below; explicit test for None
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")
30 tính toán giá trị
def initDB(name):
    global __DBNAME__  # add this line!
    if __DBNAME__ is None: # see notes below; explicit test for None
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")
31. Sử dụng phạm vi lồng nhau:

__DBNAME__ = [None] # use length-1 list as a mutable

# later, in code:  
if __DBNAME__[0] is None:
    __DBNAME__[0] = name
0

Hoặc sử dụng một đối tượng có thể gọi được:

__DBNAME__ = [None] # use length-1 list as a mutable

# later, in code:  
if __DBNAME__[0] is None:
    __DBNAME__[0] = name
1

Trong cả hai trường hợp,

cho một đối tượng có thể gọi được trong đó

def initDB(name):
    global __DBNAME__  # add this line!
    if __DBNAME__ is None: # see notes below; explicit test for None
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")
32.

Cách tiếp cận đối tượng có thể gọi có bất lợi rằng nó chậm hơn một chút và dẫn đến mã dài hơn một chút. Tuy nhiên, lưu ý rằng một bộ sưu tập các thiết bị gọi có thể chia sẻ chữ ký của chúng thông qua kế thừa:

__DBNAME__ = [None] # use length-1 list as a mutable

# later, in code:  
if __DBNAME__[0] is None:
    __DBNAME__[0] = name
2

Đối tượng có thể gói gọn trạng thái cho một số phương pháp:

__DBNAME__ = [None] # use length-1 list as a mutable

# later, in code:  
if __DBNAME__[0] is None:
    __DBNAME__[0] = name
3

Ở đây

def initDB(name):
    global __DBNAME__  # add this line!
    if __DBNAME__ is None: # see notes below; explicit test for None
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")
33,
def initDB(name):
    global __DBNAME__  # add this line!
    if __DBNAME__ is None: # see notes below; explicit test for None
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")
34 và
def initDB(name):
    global __DBNAME__  # add this line!
    if __DBNAME__ is None: # see notes below; explicit test for None
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")
35 Act như các chức năng có chung biến đếm.

Làm cách nào để sao chép một đối tượng trong Python? ¶

Nói chung, hãy thử

def initDB(name):
    global __DBNAME__  # add this line!
    if __DBNAME__ is None: # see notes below; explicit test for None
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")
36 hoặc
def initDB(name):
    global __DBNAME__  # add this line!
    if __DBNAME__ is None: # see notes below; explicit test for None
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")
37 cho trường hợp chung. Không phải tất cả các đối tượng có thể được sao chép, nhưng hầu hết có thể.

Một số đối tượng có thể được sao chép dễ dàng hơn. Từ điển có phương pháp

def initDB(name):
    global __DBNAME__  # add this line!
    if __DBNAME__ is None: # see notes below; explicit test for None
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")
38:

Trình tự có thể được sao chép bằng cách cắt:

Làm thế nào tôi có thể tìm thấy các phương thức hoặc thuộc tính của một đối tượng? ¶

Đối với một phiên bản x của một lớp do người dùng xác định,

def initDB(name):
    global __DBNAME__  # add this line!
    if __DBNAME__ is None: # see notes below; explicit test for None
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")
39 trả về một danh sách theo thứ tự chữ cái của các tên chứa các thuộc tính và phương thức và thuộc tính được xác định bởi lớp của nó.

Làm thế nào mã của tôi có thể khám phá tên của một đối tượng? ¶

Nói chung, nó có thể, bởi vì các đối tượng không thực sự có tên. Về cơ bản, gán luôn liên kết một tên với một giá trị; Điều tương tự cũng đúng với các câu lệnh

def initDB(name):
    global __DBNAME__  # add this line!
    if __DBNAME__ is None: # see notes below; explicit test for None
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")
40 và
def initDB(name):
    global __DBNAME__  # add this line!
    if __DBNAME__ is None: # see notes below; explicit test for None
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")
41, nhưng trong trường hợp đó, giá trị là có thể gọi được. Xem xét mã sau:

__DBNAME__ = [None] # use length-1 list as a mutable

# later, in code:  
if __DBNAME__[0] is None:
    __DBNAME__[0] = name
4

Có thể cho rằng lớp có một tên: mặc dù nó bị ràng buộc với hai tên và được gọi qua tên B, trường hợp được tạo vẫn được báo cáo là một ví dụ của lớp A. Tuy nhiên, không thể nói liệu tên của trường hợp đó là A hay B, Vì cả hai tên bị ràng buộc với cùng một giá trị.

Nói chung, không cần thiết cho mã của bạn để biết tên của các giá trị cụ thể. Trừ khi bạn cố tình viết các chương trình nội tâm, đây thường là một dấu hiệu cho thấy sự thay đổi của phương pháp có thể có lợi.

Trong comp.lang.python, Fredrik Lundh đã từng đưa ra một sự tương tự tuyệt vời trong câu trả lời cho câu hỏi này:

Giống như cách bạn nhận được tên của con mèo mà bạn tìm thấy trên hiên nhà của bạn: con mèo (đối tượng) không thể cho bạn biết tên của nó và nó không thực sự quan tâm - vì vậy cách duy nhất để tìm hiểu những gì nó được gọi là hỏi Tất cả hàng xóm của bạn (không gian tên) nếu đó là con mèo của họ (đối tượng)

Càng. Và don rất ngạc nhiên nếu bạn sẽ thấy rằng nó được biết đến bởi nhiều cái tên, hoặc không có tên nào cả!

Những gì mà lên với sự ưu tiên của nhà điều hành dấu phẩy? ¶

Dấu phẩy không phải là một nhà điều hành trong Python. Xem xét phiên này:

__DBNAME__ = [None] # use length-1 list as a mutable

# later, in code:  
if __DBNAME__[0] is None:
    __DBNAME__[0] = name
5

Vì dấu phẩy không phải là toán tử, mà là một dấu phân cách giữa các biểu thức, các biểu thức ở trên được đánh giá như thể bạn đã nhập:

not:

Điều tương tự cũng đúng với các toán tử gán khác nhau (

def initDB(name):
    global __DBNAME__  # add this line!
    if __DBNAME__ is None: # see notes below; explicit test for None
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")
42,
def initDB(name):
    global __DBNAME__  # add this line!
    if __DBNAME__ is None: # see notes below; explicit test for None
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")
15, v.v.). Họ không thực sự là người vận hành mà là các phân định cú pháp trong các câu lệnh chuyển nhượng.

Có một tương đương với C Cùi?: Nhà điều hành Ternary?

Có, có. Cú pháp như sau:

__DBNAME__ = [None] # use length-1 list as a mutable

# later, in code:  
if __DBNAME__[0] is None:
    __DBNAME__[0] = name
6

Trước khi cú pháp này được giới thiệu trong Python 2.5, một thành ngữ phổ biến là sử dụng các toán tử logic:

__DBNAME__ = [None] # use length-1 list as a mutable

# later, in code:  
if __DBNAME__[0] is None:
    __DBNAME__[0] = name
7

Tuy nhiên, thành ngữ này không an toàn, vì nó có thể cho kết quả sai khi on_true có giá trị boolean sai. Do đó, tốt hơn là sử dụng mẫu

def initDB(name):
    global __DBNAME__  # add this line!
    if __DBNAME__ is None: # see notes below; explicit test for None
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")
44.

Có thể viết một lớp lót bị che giấu trong Python không? ¶

Đúng. Thông thường điều này được thực hiện bằng cách làm tổ

def initDB(name):
    global __DBNAME__  # add this line!
    if __DBNAME__ is None: # see notes below; explicit test for None
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")
45 trong vòng
def initDB(name):
    global __DBNAME__  # add this line!
    if __DBNAME__ is None: # see notes below; explicit test for None
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")
45. Xem ba ví dụ sau, được điều chỉnh một chút từ ULF Bartelt:

__DBNAME__ = [None] # use length-1 list as a mutable

# later, in code:  
if __DBNAME__[0] is None:
    __DBNAME__[0] = name
8

Don Hãy thử điều này ở nhà, trẻ em!

Slash (/) trong danh sách tham số của một hàm có nghĩa là gì? ¶

Một dấu gạch chéo trong danh sách đối số của một hàm biểu thị rằng các tham số trước đó chỉ là vị trí. Các tham số chỉ có vị trí là các tham số không có tên có thể sử dụng bên ngoài. Khi gọi một hàm chấp nhận các tham số chỉ có vị trí, các đối số được ánh xạ tới các tham số chỉ dựa trên vị trí của chúng. Ví dụ,

def initDB(name):
    global __DBNAME__  # add this line!
    if __DBNAME__ is None: # see notes below; explicit test for None
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")
47 là một hàm chấp nhận các tham số chỉ có vị trí. Tài liệu của nó trông như thế này:

__DBNAME__ = [None] # use length-1 list as a mutable

# later, in code:  
if __DBNAME__[0] is None:
    __DBNAME__[0] = name
9

Việc chém ở cuối danh sách tham số có nghĩa là cả hai tham số chỉ dành cho vị trí. Do đó, việc gọi

def initDB(name):
    global __DBNAME__  # add this line!
    if __DBNAME__ is None: # see notes below; explicit test for None
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")
47 với các đối số từ khóa sẽ dẫn đến một lỗi:

class Box:
    pass

__m = Box()  # m will contain all module-level values
__m.dbname = None  # database name global in module

# later, in code:
if __m.dbname is None:
    __m.dbname = name
0

Số và chuỗi

Làm cách nào để chỉ định số nguyên thập lục phân và bát phân? ¶

Để chỉ định một chữ số bát phân, đi trước giá trị bát phân với số 0, và sau đó là một chữ số thấp hơn hoặc dưới đây. Ví dụ: để đặt biến có thể thay đổi thành giá trị octal 10 10 (8 trong thập phân), loại:

Hexadecimal cũng dễ dàng như vậy. Đơn giản chỉ cần đi trước số thập lục phân với số 0, và sau đó là một bản nhạc thấp hơn hoặc dưới đây. Các chữ số thập lục phân có thể được chỉ định ở cấp dưới hoặc chữ hoa. Ví dụ, trong phiên dịch Python:

class Box:
    pass

__m = Box()  # m will contain all module-level values
__m.dbname = None  # database name global in module

# later, in code:
if __m.dbname is None:
    __m.dbname = name
1

Tại sao -22 // 10 trả về -3? ¶

Nó chủ yếu được điều khiển bởi mong muốn rằng

def initDB(name):
    global __DBNAME__  # add this line!
    if __DBNAME__ is None: # see notes below; explicit test for None
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")
49 có cùng dấu hiệu với
def initDB(name):
    global __DBNAME__  # add this line!
    if __DBNAME__ is None: # see notes below; explicit test for None
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")
50. Nếu bạn muốn điều đó, và cũng muốn:

class Box:
    pass

__m = Box()  # m will contain all module-level values
__m.dbname = None  # database name global in module

# later, in code:
if __m.dbname is None:
    __m.dbname = name
2

Sau đó, phân chia số nguyên phải trả lại sàn. C cũng yêu cầu danh tính đó phải giữ, và sau đó các trình biên dịch cắt ngắn

def initDB(name):
    global __DBNAME__  # add this line!
    if __DBNAME__ is None: # see notes below; explicit test for None
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")
51 cần phải làm cho
def initDB(name):
    global __DBNAME__  # add this line!
    if __DBNAME__ is None: # see notes below; explicit test for None
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")
49 có cùng dấu hiệu
def initDB(name):
    global __DBNAME__  # add this line!
    if __DBNAME__ is None: # see notes below; explicit test for None
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")
53.

Có rất ít trường hợp sử dụng thực sự cho

def initDB(name):
    global __DBNAME__  # add this line!
    if __DBNAME__ is None: # see notes below; explicit test for None
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")
49 khi
def initDB(name):
    global __DBNAME__  # add this line!
    if __DBNAME__ is None: # see notes below; explicit test for None
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")
50 là âm. Khi
def initDB(name):
    global __DBNAME__  # add this line!
    if __DBNAME__ is None: # see notes below; explicit test for None
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")
50 là tích cực, có rất nhiều, và trong hầu hết tất cả chúng, nó rất hữu ích cho
def initDB(name):
    global __DBNAME__  # add this line!
    if __DBNAME__ is None: # see notes below; explicit test for None
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")
49 là
def initDB(name):
    global __DBNAME__  # add this line!
    if __DBNAME__ is None: # see notes below; explicit test for None
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")
58. Nếu đồng hồ nói 10 bây giờ, nó đã nói gì 200 giờ trước?
def initDB(name):
    global __DBNAME__  # add this line!
    if __DBNAME__ is None: # see notes below; explicit test for None
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")
59 là hữu ích;
def initDB(name):
    global __DBNAME__  # add this line!
    if __DBNAME__ is None: # see notes below; explicit test for None
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")
60 là một lỗi đang chờ để cắn.

Làm cách nào để nhận thuộc tính int theo nghĩa đen thay vì cú pháp? ¶

Cố gắng tra cứu một thuộc tính nghĩa đen

def initDB(name):
    global __DBNAME__  # add this line!
    if __DBNAME__ is None: # see notes below; explicit test for None
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")
25 theo cách thông thường gây ra lỗi cú pháp vì khoảng thời gian được xem là một điểm thập phân:

class Box:
    pass

__m = Box()  # m will contain all module-level values
__m.dbname = None  # database name global in module

# later, in code:
if __m.dbname is None:
    __m.dbname = name
3

Giải pháp là tách chữ theo nghĩa đen với khoảng thời gian bằng một không gian hoặc dấu ngoặc đơn.

class Box:
    pass

__m = Box()  # m will contain all module-level values
__m.dbname = None  # database name global in module

# later, in code:
if __m.dbname is None:
    __m.dbname = name
4

Làm cách nào để chuyển đổi một chuỗi thành một số? ¶

Đối với các số nguyên, hãy sử dụng hàm tạo loại

def initDB(name):
    global __DBNAME__  # add this line!
    if __DBNAME__ is None: # see notes below; explicit test for None
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")
62 tích hợp, ví dụ:
def initDB(name):
    global __DBNAME__  # add this line!
    if __DBNAME__ is None: # see notes below; explicit test for None
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")
63. Tương tự,
def initDB(name):
    global __DBNAME__  # add this line!
    if __DBNAME__ is None: # see notes below; explicit test for None
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")
64 chuyển đổi thành điểm nổi, ví dụ:
def initDB(name):
    global __DBNAME__  # add this line!
    if __DBNAME__ is None: # see notes below; explicit test for None
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")
65.

Theo mặc định, chúng diễn giải số là thập phân, do đó

def initDB(name):
    global __DBNAME__  # add this line!
    if __DBNAME__ is None: # see notes below; explicit test for None
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")
66 giữ đúng và
def initDB(name):
    global __DBNAME__  # add this line!
    if __DBNAME__ is None: # see notes below; explicit test for None
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")
67 tăng
def initDB(name):
    global __DBNAME__  # add this line!
    if __DBNAME__ is None: # see notes below; explicit test for None
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")
68.
def initDB(name):
    global __DBNAME__  # add this line!
    if __DBNAME__ is None: # see notes below; explicit test for None
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")
69 lấy cơ sở để chuyển đổi từ đối số tùy chọn thứ hai, do đó
def initDB(name):
    global __DBNAME__  # add this line!
    if __DBNAME__ is None: # see notes below; explicit test for None
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")
70. Nếu cơ sở được chỉ định là 0, số được giải thích bằng các quy tắc của Python: một ‘0o, chỉ ra bát phân và‘ 0x, chỉ ra một số hex.

Không sử dụng chức năng tích hợp

def initDB(name):
    global __DBNAME__  # add this line!
    if __DBNAME__ is None: # see notes below; explicit test for None
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")
71 nếu tất cả những gì bạn cần là chuyển đổi chuỗi thành số.
def initDB(name):
    global __DBNAME__  # add this line!
    if __DBNAME__ is None: # see notes below; explicit test for None
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")
71 sẽ chậm hơn đáng kể và nó có nguy cơ bảo mật: ai đó có thể truyền cho bạn một biểu hiện python có thể có tác dụng phụ không mong muốn. Ví dụ, ai đó có thể vượt qua
def initDB(name):
    global __DBNAME__  # add this line!
    if __DBNAME__ is None: # see notes below; explicit test for None
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")
73 sẽ xóa thư mục nhà của bạn.

def initDB(name):
    global __DBNAME__  # add this line!
    if __DBNAME__ is None: # see notes below; explicit test for None
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")
71 cũng có tác dụng diễn giải các số là biểu thức python, do đó, ví dụ:
def initDB(name):
    global __DBNAME__  # add this line!
    if __DBNAME__ is None: # see notes below; explicit test for None
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")
75 đưa ra lỗi cú pháp vì Python không cho phép dẫn đầu ‘0, trong một số thập phân (ngoại trừ‘ 0,).

Làm cách nào để chuyển đổi một số thành một chuỗi? ¶

Để chuyển đổi, ví dụ: số 144 thành chuỗi ‘144, sử dụng hàm tạo loại tích hợp

def initDB(name):
    global __DBNAME__  # add this line!
    if __DBNAME__ is None: # see notes below; explicit test for None
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")
76. Nếu bạn muốn biểu diễn thập lục phân hoặc bát phân, hãy sử dụng các hàm tích hợp
def initDB(name):
    global __DBNAME__  # add this line!
    if __DBNAME__ is None: # see notes below; explicit test for None
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")
77 hoặc
def initDB(name):
    global __DBNAME__  # add this line!
    if __DBNAME__ is None: # see notes below; explicit test for None
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")
78. Để biết định dạng ưa thích, hãy xem các phần Syntax Chuỗi và Chuỗi định dạng được định dạng, ví dụ:
def initDB(name):
    global __DBNAME__  # add this line!
    if __DBNAME__ is None: # see notes below; explicit test for None
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")
79 mang lại
def initDB(name):
    global __DBNAME__  # add this line!
    if __DBNAME__ is None: # see notes below; explicit test for None
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")
80 và
def initDB(name):
    global __DBNAME__  # add this line!
    if __DBNAME__ is None: # see notes below; explicit test for None
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")
81 mang lại
def initDB(name):
    global __DBNAME__  # add this line!
    if __DBNAME__ is None: # see notes below; explicit test for None
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")
82.Formatted string literals and Format String Syntax sections, e.g.
def initDB(name):
    global __DBNAME__  # add this line!
    if __DBNAME__ is None: # see notes below; explicit test for None
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")
79 yields
def initDB(name):
    global __DBNAME__  # add this line!
    if __DBNAME__ is None: # see notes below; explicit test for None
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")
80 and
def initDB(name):
    global __DBNAME__  # add this line!
    if __DBNAME__ is None: # see notes below; explicit test for None
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")
81 yields
def initDB(name):
    global __DBNAME__  # add this line!
    if __DBNAME__ is None: # see notes below; explicit test for None
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")
82.

Làm cách nào để sửa đổi một chuỗi tại chỗ? ¶

Bạn có thể, vì dây là bất biến. Trong hầu hết các tình huống, bạn chỉ nên xây dựng một chuỗi mới từ các phần khác nhau mà bạn muốn lắp ráp. Tuy nhiên, nếu bạn cần một đối tượng có khả năng sửa đổi dữ liệu Unicode tại chỗ, hãy thử sử dụng đối tượng

def initDB(name):
    global __DBNAME__  # add this line!
    if __DBNAME__ is None: # see notes below; explicit test for None
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")
83 hoặc mô-đun
def initDB(name):
    global __DBNAME__  # add this line!
    if __DBNAME__ is None: # see notes below; explicit test for None
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")
84:

class Box:
    pass

__m = Box()  # m will contain all module-level values
__m.dbname = None  # database name global in module

# later, in code:
if __m.dbname is None:
    __m.dbname = name
5

Làm cách nào để sử dụng chuỗi để gọi các chức năng/phương thức? ¶

Có nhiều kỹ thuật khác nhau.

  • Tốt nhất là sử dụng một từ điển ánh xạ các chuỗi theo các chức năng. Ưu điểm chính của kỹ thuật này là các chuỗi không cần phải khớp với tên của các chức năng. Đây cũng là kỹ thuật chính được sử dụng để mô phỏng cấu trúc trường hợp:

    class Box:
        pass
    
    __m = Box()  # m will contain all module-level values
    __m.dbname = None  # database name global in module
    
    # later, in code:
    if __m.dbname is None:
        __m.dbname = name
    
    6

  • Sử dụng chức năng tích hợp

    def initDB(name):
        global __DBNAME__  # add this line!
        if __DBNAME__ is None: # see notes below; explicit test for None
            __DBNAME__ = name
        else:
            raise RuntimeError("Database name has already been set.")
    
    85:

    class Box:
        pass
    
    __m = Box()  # m will contain all module-level values
    __m.dbname = None  # database name global in module
    
    # later, in code:
    if __m.dbname is None:
        __m.dbname = name
    
    7

    Lưu ý rằng

    def initDB(name):
        global __DBNAME__  # add this line!
        if __DBNAME__ is None: # see notes below; explicit test for None
            __DBNAME__ = name
        else:
            raise RuntimeError("Database name has already been set.")
    
    85 hoạt động trên bất kỳ đối tượng nào, bao gồm các lớp, phiên bản lớp, mô -đun, v.v.

    Điều này được sử dụng ở một số nơi trong thư viện tiêu chuẩn, như thế này:

    class Box:
        pass
    
    __m = Box()  # m will contain all module-level values
    __m.dbname = None  # database name global in module
    
    # later, in code:
    if __m.dbname is None:
        __m.dbname = name
    
    8

  • Sử dụng

    def initDB(name):
        global __DBNAME__  # add this line!
        if __DBNAME__ is None: # see notes below; explicit test for None
            __DBNAME__ = name
        else:
            raise RuntimeError("Database name has already been set.")
    
    87 để giải quyết tên chức năng:

    class Box:
        pass
    
    __m = Box()  # m will contain all module-level values
    __m.dbname = None  # database name global in module
    
    # later, in code:
    if __m.dbname is None:
        __m.dbname = name
    
    9

Có tương đương với Perl xông Chomp () để loại bỏ các dòng mới ra khỏi dây không? ¶

Bạn có thể sử dụng

def initDB(name):
    global __DBNAME__  # add this line!
    if __DBNAME__ is None: # see notes below; explicit test for None
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")
88 để loại bỏ tất cả các lần xuất hiện của bất kỳ Terminator dòng nào từ cuối chuỗi
def initDB(name):
    global __DBNAME__  # add this line!
    if __DBNAME__ is None: # see notes below; explicit test for None
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")
89 mà không cần loại bỏ khoảng trắng kéo dài khác. Nếu chuỗi
def initDB(name):
    global __DBNAME__  # add this line!
    if __DBNAME__ is None: # see notes below; explicit test for None
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")
89 đại diện cho nhiều dòng, với một số dòng trống ở cuối, các thiết bị đầu cuối dòng cho tất cả các dòng trống sẽ bị xóa:

>>> x = 10
>>> def bar():
...     print(x)
>>> bar()
10
0

Vì điều này thường chỉ mong muốn khi đọc văn bản một dòng tại một thời điểm, sử dụng

def initDB(name):
    global __DBNAME__  # add this line!
    if __DBNAME__ is None: # see notes below; explicit test for None
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")
91 theo cách này hoạt động tốt.

Có tương đương với scanf () hoặc sscanf () không? ¶

Không như vậy.

Đối với phân tích cú pháp đầu vào đơn giản, cách tiếp cận dễ nhất thường là chia dòng thành các từ được phân phối bằng khoảng trắng bằng phương pháp

def initDB(name):
    global __DBNAME__  # add this line!
    if __DBNAME__ is None: # see notes below; explicit test for None
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")
92 của các đối tượng chuỗi và sau đó chuyển đổi chuỗi thập phân thành các giá trị số bằng cách sử dụng
def initDB(name):
    global __DBNAME__  # add this line!
    if __DBNAME__ is None: # see notes below; explicit test for None
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")
62 hoặc
def initDB(name):
    global __DBNAME__  # add this line!
    if __DBNAME__ is None: # see notes below; explicit test for None
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")
64.
def initDB(name):
    global __DBNAME__  # add this line!
    if __DBNAME__ is None: # see notes below; explicit test for None
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")
92 hỗ trợ một tham số tùy chọn của SEP, rất hữu ích nếu dòng sử dụng một cái gì đó khác ngoài khoảng trắng làm dấu phân cách.

Đối với phân tích cú pháp đầu vào phức tạp hơn, các biểu thức chính quy mạnh hơn C Lau

def initDB(name):
    global __DBNAME__  # add this line!
    if __DBNAME__ is None: # see notes below; explicit test for None
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")
96 và phù hợp hơn cho nhiệm vụ.

Unicodedecodeerror, hoặc unicodeEncodeError có nghĩa là gì? ¶

Xem Unicode Howto.Unicode HOWTO.

Màn biểu diễn¶

Chương trình của tôi quá chậm. Làm cách nào để tăng tốc nó? ¶

Nói chung, đó là một điều khó khăn. Đầu tiên, đây là danh sách những điều cần nhớ trước khi lặn thêm:

  • Đặc điểm hiệu suất khác nhau giữa việc triển khai Python. Câu hỏi thường gặp này tập trung vào Cpython.CPython.

  • Hành vi có thể thay đổi trên các hệ điều hành, đặc biệt là khi nói về I/O hoặc đa luồng.

  • Bạn nên luôn luôn tìm thấy các điểm nóng trong chương trình của mình trước khi cố gắng tối ưu hóa bất kỳ mã nào (xem mô -đun

    def initDB(name):
        global __DBNAME__  # add this line!
        if __DBNAME__ is None: # see notes below; explicit test for None
            __DBNAME__ = name
        else:
            raise RuntimeError("Database name has already been set.")
    
    97).

  • Viết các tập lệnh điểm chuẩn sẽ cho phép bạn lặp lại nhanh chóng khi tìm kiếm các cải tiến (xem mô -đun

    def initDB(name):
        global __DBNAME__  # add this line!
        if __DBNAME__ is None: # see notes below; explicit test for None
            __DBNAME__ = name
        else:
            raise RuntimeError("Database name has already been set.")
    
    98).

  • Rất khuyến khích có phạm vi bảo hiểm mã tốt (thông qua kiểm tra đơn vị hoặc bất kỳ kỹ thuật nào khác) trước khi có khả năng giới thiệu các hồi quy ẩn trong các tối ưu hóa tinh vi.

Điều đó đang được nói, có nhiều thủ thuật để tăng tốc mã Python. Dưới đây là một số nguyên tắc chung đi một chặng đường dài để đạt được mức hiệu suất chấp nhận được:

  • Làm cho các thuật toán của bạn nhanh hơn (hoặc thay đổi thành những thuật toán nhanh hơn) có thể mang lại lợi ích lớn hơn nhiều so với việc cố gắng thực hiện các thủ thuật tối ưu hóa vi mô trên tất cả các mã của bạn.

  • Sử dụng các cấu trúc dữ liệu phù hợp. Tài liệu nghiên cứu cho các loại tích hợp và mô-đun

    def initDB(name):
        global __DBNAME__  # add this line!
        if __DBNAME__ is None: # see notes below; explicit test for None
            __DBNAME__ = name
        else:
            raise RuntimeError("Database name has already been set.")
    
    99.Built-in Types and the
    def initDB(name):
        global __DBNAME__  # add this line!
        if __DBNAME__ is None: # see notes below; explicit test for None
            __DBNAME__ = name
        else:
            raise RuntimeError("Database name has already been set.")
    
    99 module.

  • Khi thư viện tiêu chuẩn cung cấp một nguyên thủy để làm một cái gì đó, có khả năng (mặc dù không được đảm bảo) nhanh hơn bất kỳ sự thay thế nào bạn có thể nghĩ ra. Điều này có thể đúng với các nguyên thủy được viết bằng C, chẳng hạn như tích hợp và một số loại mở rộng. Ví dụ: đảm bảo sử dụng phương thức tích hợp

    __DBNAME__ = [None] # use length-1 list as a mutable
    
    # later, in code:  
    if __DBNAME__[0] is None:
        __DBNAME__[0] = name
    
    00 hoặc hàm
    __DBNAME__ = [None] # use length-1 list as a mutable
    
    # later, in code:  
    if __DBNAME__[0] is None:
        __DBNAME__[0] = name
    
    01 liên quan để sắp xếp (và xem cách sắp xếp cách để biết các ví dụ về cách sử dụng nâng cao vừa phải).Sorting HOW TO for examples of moderately advanced usage).

  • Trừu tượng có xu hướng tạo ra sự bất công và buộc thông dịch viên làm việc nhiều hơn. Nếu mức độ liên tục vượt xa số lượng công việc hữu ích được thực hiện, chương trình của bạn sẽ chậm hơn. Bạn nên tránh sự trừu tượng quá mức, đặc biệt là dưới dạng các hàm hoặc phương pháp nhỏ (cũng thường gây bất lợi cho khả năng đọc).

Nếu bạn đã đạt đến giới hạn của những gì Python thuần túy có thể cho phép, có những công cụ để đưa bạn đi xa hơn. Ví dụ, Cython có thể biên dịch một phiên bản Python được sửa đổi một chút thành tiện ích mở rộng C và có thể được sử dụng trên nhiều nền tảng khác nhau. Cython có thể tận dụng việc biên dịch (và chú thích loại tùy chọn) để làm cho mã của bạn nhanh hơn đáng kể so với khi được giải thích. Nếu bạn tự tin vào các kỹ năng lập trình C của mình, bạn cũng có thể tự viết mô -đun mở rộng C.write a C extension module yourself.

Cách hiệu quả nhất để kết hợp nhiều chuỗi với nhau là gì? ¶

Các đối tượng

def initDB(name):
    global __DBNAME__  # add this line!
    if __DBNAME__ is None: # see notes below; explicit test for None
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")
24 và
__DBNAME__ = [None] # use length-1 list as a mutable

# later, in code:  
if __DBNAME__[0] is None:
    __DBNAME__[0] = name
03 là bất biến, do đó liên kết nhiều chuỗi với nhau là không hiệu quả vì mỗi lần ghép tạo ra một đối tượng mới. Trong trường hợp chung, tổng chi phí thời gian chạy là bậc hai trong tổng chiều dài chuỗi.

Để tích lũy nhiều đối tượng

def initDB(name):
    global __DBNAME__  # add this line!
    if __DBNAME__ is None: # see notes below; explicit test for None
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")
24, thành ngữ được đề xuất là đặt chúng vào danh sách và gọi
__DBNAME__ = [None] # use length-1 list as a mutable

# later, in code:  
if __DBNAME__[0] is None:
    __DBNAME__[0] = name
05 ở cuối:

>>> x = 10
>>> def bar():
...     print(x)
>>> bar()
10
1

(Một thành ngữ hiệu quả hợp lý khác là sử dụng

def initDB(name):
    global __DBNAME__  # add this line!
    if __DBNAME__ is None: # see notes below; explicit test for None
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")
83)

Để tích lũy nhiều đối tượng

__DBNAME__ = [None] # use length-1 list as a mutable

# later, in code:  
if __DBNAME__[0] is None:
    __DBNAME__[0] = name
03, thành ngữ được đề xuất là mở rộng một đối tượng
__DBNAME__ = [None] # use length-1 list as a mutable

# later, in code:  
if __DBNAME__[0] is None:
    __DBNAME__[0] = name
08 bằng cách sử dụng cách ghép tại chỗ (toán tử
def initDB(name):
    global __DBNAME__  # add this line!
    if __DBNAME__ is None: # see notes below; explicit test for None
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")
15):

>>> x = 10
>>> def bar():
...     print(x)
>>> bar()
10
2

Trình tự (Tuples/Danh sách) ¶

Làm cách nào để chuyển đổi giữa các bộ đếm và danh sách? ¶

Loại cấu trúc loại

__DBNAME__ = [None] # use length-1 list as a mutable

# later, in code:  
if __DBNAME__[0] is None:
    __DBNAME__[0] = name
10 chuyển đổi bất kỳ chuỗi nào (thực ra, bất kỳ điều gì có thể lặp lại) thành một tuple với cùng một mục theo cùng một thứ tự.

Ví dụ,

__DBNAME__ = [None] # use length-1 list as a mutable

# later, in code:  
if __DBNAME__[0] is None:
    __DBNAME__[0] = name
11 mang lại
__DBNAME__ = [None] # use length-1 list as a mutable

# later, in code:  
if __DBNAME__[0] is None:
    __DBNAME__[0] = name
12 và
__DBNAME__ = [None] # use length-1 list as a mutable

# later, in code:  
if __DBNAME__[0] is None:
    __DBNAME__[0] = name
13 mang lại
__DBNAME__ = [None] # use length-1 list as a mutable

# later, in code:  
if __DBNAME__[0] is None:
    __DBNAME__[0] = name
14. Nếu đối số là một tuple, nó không tạo ra một bản sao mà trả về cùng một đối tượng, vì vậy thật rẻ khi gọi
__DBNAME__ = [None] # use length-1 list as a mutable

# later, in code:  
if __DBNAME__[0] is None:
    __DBNAME__[0] = name
15 khi bạn không chắc chắn rằng một đối tượng đã là một tuple.

Loại xây dựng

__DBNAME__ = [None] # use length-1 list as a mutable

# later, in code:  
if __DBNAME__[0] is None:
    __DBNAME__[0] = name
16 chuyển đổi bất kỳ chuỗi hoặc có thể lặp lại thành một danh sách với cùng một mục theo cùng một thứ tự. Ví dụ,
__DBNAME__ = [None] # use length-1 list as a mutable

# later, in code:  
if __DBNAME__[0] is None:
    __DBNAME__[0] = name
17 mang lại
__DBNAME__ = [None] # use length-1 list as a mutable

# later, in code:  
if __DBNAME__[0] is None:
    __DBNAME__[0] = name
18 và
__DBNAME__ = [None] # use length-1 list as a mutable

# later, in code:  
if __DBNAME__[0] is None:
    __DBNAME__[0] = name
19 mang lại
__DBNAME__ = [None] # use length-1 list as a mutable

# later, in code:  
if __DBNAME__[0] is None:
    __DBNAME__[0] = name
20. Nếu đối số là một danh sách, nó sẽ tạo ra một bản sao giống như
__DBNAME__ = [None] # use length-1 list as a mutable

# later, in code:  
if __DBNAME__[0] is None:
    __DBNAME__[0] = name
21.

Những gì một chỉ số tiêu cực? ¶

Trình tự Python được lập chỉ mục với số dương và số âm. Đối với các số dương 0 là chỉ số 1 đầu tiên là chỉ số thứ hai và vv. Đối với các chỉ số âm -1 là chỉ số cuối cùng và -2 là chỉ mục áp chót (bên cạnh cuối cùng) và vv. Hãy nghĩ về

__DBNAME__ = [None] # use length-1 list as a mutable

# later, in code:  
if __DBNAME__[0] is None:
    __DBNAME__[0] = name
22 giống như
__DBNAME__ = [None] # use length-1 list as a mutable

# later, in code:  
if __DBNAME__[0] is None:
    __DBNAME__[0] = name
23.

Sử dụng các chỉ số tiêu cực có thể rất thuận tiện. Ví dụ:

__DBNAME__ = [None] # use length-1 list as a mutable

# later, in code:  
if __DBNAME__[0] is None:
    __DBNAME__[0] = name
24 là tất cả các chuỗi ngoại trừ ký tự cuối cùng của nó, rất hữu ích cho việc loại bỏ đường nối mới khỏi một chuỗi.

Làm thế nào để tôi lặp lại theo một chuỗi theo thứ tự ngược lại? ¶

Sử dụng chức năng tích hợp

__DBNAME__ = [None] # use length-1 list as a mutable

# later, in code:  
if __DBNAME__[0] is None:
    __DBNAME__[0] = name
25:

>>> x = 10
>>> def bar():
...     print(x)
>>> bar()
10
3

Điều này giành được chạm vào chuỗi ban đầu của bạn, nhưng xây dựng một bản sao mới với thứ tự đảo ngược để lặp lại.

Làm thế nào để bạn xóa các bản sao khỏi danh sách? ¶

Xem Sách nấu ăn Python để thảo luận dài về nhiều cách để làm điều này:

Nếu bạn không có tâm trí sắp xếp lại danh sách, hãy sắp xếp nó và sau đó quét từ cuối danh sách, xóa các bản sao khi bạn đi:

>>> x = 10
>>> def bar():
...     print(x)
>>> bar()
10
4

Nếu tất cả các yếu tố của danh sách có thể được sử dụng làm khóa tập hợp (tức là tất cả chúng đều có thể băm) thì điều này thường nhanh hơnhashable) this is often faster

>>> x = 10
>>> def bar():
...     print(x)
>>> bar()
10
5

Điều này chuyển đổi danh sách thành một tập hợp, do đó loại bỏ các bản sao, và sau đó quay lại danh sách.

Làm thế nào để bạn xóa nhiều mục khỏi danh sách

Như với việc loại bỏ các bản sao, việc lặp lại một cách rõ ràng với một điều kiện xóa là một khả năng. Tuy nhiên, việc sử dụng thay thế lát cắt bằng một lần lặp về phía trước hoặc rõ ràng sẽ dễ dàng và nhanh hơn. Đây là ba biến thể .:

>>> x = 10
>>> def bar():
...     print(x)
>>> bar()
10
6

Danh sách hiểu có thể nhanh nhất.

Làm thế nào để bạn tạo ra một mảng trong Python? ¶

Sử dụng danh sách:

>>> x = 10
>>> def bar():
...     print(x)
>>> bar()
10
7

Danh sách tương đương với các mảng C hoặc Pascal trong độ phức tạp thời gian của chúng; Sự khác biệt chính là danh sách Python có thể chứa các đối tượng thuộc nhiều loại khác nhau.

Mô -đun

def initDB(name):
    global __DBNAME__  # add this line!
    if __DBNAME__ is None: # see notes below; explicit test for None
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")
84 cũng cung cấp các phương thức để tạo các mảng các loại cố định với các biểu diễn nhỏ gọn, nhưng chúng chậm hơn so với danh sách. Cũng lưu ý rằng các gói Numpy và bên thứ ba khác cũng xác định các cấu trúc giống như mảng với các đặc điểm khác nhau.

Để có được danh sách liên kết theo kiểu LISP, bạn có thể mô phỏng các ô khuyết điểm bằng cách sử dụng các bộ dữ liệu:

>>> x = 10
>>> def bar():
...     print(x)
>>> bar()
10
8

Nếu khả năng đột biến là mong muốn, bạn có thể sử dụng danh sách thay vì bộ dữ liệu. Ở đây, tương tự của chiếc xe Lisp là

__DBNAME__ = [None] # use length-1 list as a mutable

# later, in code:  
if __DBNAME__[0] is None:
    __DBNAME__[0] = name
27 và tương tự của CDR là
__DBNAME__ = [None] # use length-1 list as a mutable

# later, in code:  
if __DBNAME__[0] is None:
    __DBNAME__[0] = name
28. Chỉ làm điều này nếu bạn chắc chắn rằng bạn thực sự cần, bởi vì nó thường chậm hơn rất nhiều so với việc sử dụng danh sách Python.

Làm cách nào để tạo một danh sách đa chiều? ¶

Bạn có thể đã cố gắng tạo ra một mảng đa chiều như thế này:

Điều này có vẻ chính xác nếu bạn in nó:

>>> x = 10
>>> def bar():
...     print(x)
>>> bar()
10
9

Nhưng khi bạn gán một giá trị, nó sẽ xuất hiện ở nhiều nơi:

>>> x = 10
>>> def foo():
...     print(x)
...     x += 1
0

Lý do là sao chép một danh sách với

import foo
print(foo.X)  # prints 1
73 không tạo ra các bản sao, nó chỉ tạo ra các tham chiếu đến các đối tượng hiện có.
__DBNAME__ = [None] # use length-1 list as a mutable

# later, in code:  
if __DBNAME__[0] is None:
    __DBNAME__[0] = name
30 tạo ra một danh sách chứa 3 tham chiếu đến cùng một danh sách độ dài hai. Các thay đổi thành một hàng sẽ hiển thị trong tất cả các hàng, điều này gần như chắc chắn không phải là điều bạn muốn.

Cách tiếp cận được đề xuất là tạo một danh sách độ dài mong muốn trước và sau đó điền vào mỗi phần tử với một danh sách mới được tạo:

>>> x = 10
>>> def foo():
...     print(x)
...     x += 1
1

Điều này tạo ra một danh sách chứa 3 danh sách khác nhau về độ dài hai. Bạn cũng có thể sử dụng danh sách hiểu biết:

>>> x = 10
>>> def foo():
...     print(x)
...     x += 1
2

Hoặc, bạn có thể sử dụng một tiện ích mở rộng cung cấp kiểu dữ liệu ma trận; Numpy là người nổi tiếng nhất.

Làm cách nào để áp dụng một phương thức cho một chuỗi các đối tượng? ¶

Sử dụng danh sách hiểu biết:

>>> x = 10
>>> def foo():
...     print(x)
...     x += 1
3

Tại sao a_tuple [i] += [‘item,] tăng một ngoại lệ khi bổ sung hoạt động? ¶

Điều này là do sự kết hợp của thực tế là các toán tử gán tăng cường là các toán tử gán và sự khác biệt giữa các đối tượng có thể thay đổi và bất biến trong Python.

Cuộc thảo luận này áp dụng nói chung khi các nhà khai thác gán tăng cường được áp dụng cho các yếu tố của một tuple chỉ ra các đối tượng có thể thay đổi, nhưng chúng tôi sẽ sử dụng

def initDB(name):
    global __DBNAME__  # add this line!
    if __DBNAME__ is None: # see notes below; explicit test for None
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")
21 và
def initDB(name):
    global __DBNAME__  # add this line!
    if __DBNAME__ is None: # see notes below; explicit test for None
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")
15 làm mẫu mực của chúng tôi.

Nếu bạn đã viết:

>>> x = 10
>>> def foo():
...     print(x)
...     x += 1
4

Lý do cho ngoại lệ phải rõ ràng ngay lập tức:

import foo
print(foo.X)  # prints 1
41 được thêm vào đối tượng
__DBNAME__ = [None] # use length-1 list as a mutable

# later, in code:  
if __DBNAME__[0] is None:
    __DBNAME__[0] = name
34 điểm vào (
import foo
print(foo.X)  # prints 1
41), tạo ra đối tượng kết quả,
import foo
print(foo.X)  # prints 1
59, nhưng khi chúng tôi cố gắng gán kết quả của tính toán,
import foo
print(foo.X)  # prints 1
59, cho phần tử
import foo
print(foo.X)  # prints 1
40 , chúng ta gặp lỗi vì chúng ta không thể thay đổi yếu tố của một bộ tuple.

Theo bìa, những gì mà câu lệnh gán tăng cường này đang làm là khoảng này:

>>> x = 10
>>> def foo():
...     print(x)
...     x += 1
5

Đây là phần gán của hoạt động tạo ra lỗi, vì một tuple là bất biến.

Khi bạn viết một cái gì đó như:

>>> x = 10
>>> def foo():
...     print(x)
...     x += 1
6

Ngoại lệ là đáng ngạc nhiên hơn một chút, và thậm chí còn ngạc nhiên hơn là mặc dù có một lỗi, nhưng phần phụ đã hoạt động:

>>> x = 10
>>> def foo():
...     print(x)
...     x += 1
7

Để xem lý do tại sao điều này xảy ra, bạn cần biết rằng (a) nếu một đối tượng thực hiện phương thức ma thuật

__DBNAME__ = [None] # use length-1 list as a mutable

# later, in code:  
if __DBNAME__[0] is None:
    __DBNAME__[0] = name
39, nó sẽ được gọi khi bài tập tăng cường
def initDB(name):
    global __DBNAME__  # add this line!
    if __DBNAME__ is None: # see notes below; explicit test for None
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")
15 được thực thi và giá trị trả về của nó là những gì được sử dụng trong câu lệnh gán; và (b) cho danh sách,
__DBNAME__ = [None] # use length-1 list as a mutable

# later, in code:  
if __DBNAME__[0] is None:
    __DBNAME__[0] = name
39 tương đương với việc gọi
__DBNAME__ = [None] # use length-1 list as a mutable

# later, in code:  
if __DBNAME__[0] is None:
    __DBNAME__[0] = name
42 trong danh sách và trả lại danh sách. Đó là lý do tại sao chúng tôi nói rằng đối với các danh sách,
def initDB(name):
    global __DBNAME__  # add this line!
    if __DBNAME__ is None: # see notes below; explicit test for None
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")
15 là một tốc ký của người Viking cho
__DBNAME__ = [None] # use length-1 list as a mutable

# later, in code:  
if __DBNAME__[0] is None:
    __DBNAME__[0] = name
44:

>>> x = 10
>>> def foo():
...     print(x)
...     x += 1
8

Điều này tương đương với:

>>> x = 10
>>> def foo():
...     print(x)
...     x += 1
9

Đối tượng được chỉ ra bởi a_list đã bị đột biến và con trỏ đến đối tượng đột biến được gán lại cho

def initDB(name):
    global __DBNAME__  # add this line!
    if __DBNAME__ is None: # see notes below; explicit test for None
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")
18. Kết quả cuối cùng của bài tập là không có op, vì nó là một con trỏ tới cùng một đối tượng mà
def initDB(name):
    global __DBNAME__  # add this line!
    if __DBNAME__ is None: # see notes below; explicit test for None
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")
18 trước đây đã chỉ ra, nhưng bài tập vẫn xảy ra.

Do đó, trong ví dụ Tuple của chúng tôi, những gì đang xảy ra tương đương với:

>>> foo()
Traceback (most recent call last):
  ...
UnboundLocalError: local variable 'x' referenced before assignment
0

__DBNAME__ = [None] # use length-1 list as a mutable

# later, in code:  
if __DBNAME__[0] is None:
    __DBNAME__[0] = name
39 thành công, và do đó, danh sách được mở rộng, nhưng mặc dù
__DBNAME__ = [None] # use length-1 list as a mutable

# later, in code:  
if __DBNAME__[0] is None:
    __DBNAME__[0] = name
48 chỉ vào cùng một đối tượng mà
__DBNAME__ = [None] # use length-1 list as a mutable

# later, in code:  
if __DBNAME__[0] is None:
    __DBNAME__[0] = name
34 đã chỉ ra, nhiệm vụ cuối cùng đó vẫn dẫn đến một lỗi, bởi vì các bộ dữ liệu là bất biến.

Tôi muốn thực hiện một loại phức tạp: Bạn có thể thực hiện một phép biến đổi Schwartzian trong Python không?

Kỹ thuật này, được quy cho Randal Schwartz của cộng đồng Perl, sắp xếp các yếu tố của một danh sách theo một số liệu ánh xạ từng yếu tố theo giá trị sắp xếp của nó. Trong Python, hãy sử dụng đối số

__DBNAME__ = [None] # use length-1 list as a mutable

# later, in code:  
if __DBNAME__[0] is None:
    __DBNAME__[0] = name
50 cho phương thức
__DBNAME__ = [None] # use length-1 list as a mutable

# later, in code:  
if __DBNAME__[0] is None:
    __DBNAME__[0] = name
00:

>>> foo()
Traceback (most recent call last):
  ...
UnboundLocalError: local variable 'x' referenced before assignment
1

Làm cách nào để sắp xếp một danh sách theo các giá trị từ danh sách khác? ¶

Hợp nhất chúng thành một trình lặp của các bộ dữ liệu, sắp xếp danh sách kết quả, và sau đó chọn ra phần tử bạn muốn.

>>> foo()
Traceback (most recent call last):
  ...
UnboundLocalError: local variable 'x' referenced before assignment
2

Các đối tượng¶

Lớp học là gì? ¶

Một lớp là loại đối tượng cụ thể được tạo bằng cách thực thi một câu lệnh lớp. Các đối tượng lớp được sử dụng làm mẫu để tạo các đối tượng thể hiện, thể hiện cả dữ liệu (thuộc tính) và mã (phương thức) cụ thể cho kiểu dữ liệu.

Một lớp có thể dựa trên một hoặc nhiều lớp khác, được gọi là lớp cơ sở của nó. Sau đó, nó kế thừa các thuộc tính và phương thức của các lớp cơ sở của nó. Điều này cho phép một mô hình đối tượng được tinh chỉnh liên tiếp bởi sự kế thừa. Bạn có thể có một lớp

__DBNAME__ = [None] # use length-1 list as a mutable

# later, in code:  
if __DBNAME__[0] is None:
    __DBNAME__[0] = name
52 chung cung cấp các phương thức truy cập cơ bản cho hộp thư và các lớp con như
__DBNAME__ = [None] # use length-1 list as a mutable

# later, in code:  
if __DBNAME__[0] is None:
    __DBNAME__[0] = name
53,
__DBNAME__ = [None] # use length-1 list as a mutable

# later, in code:  
if __DBNAME__[0] is None:
    __DBNAME__[0] = name
54,
__DBNAME__ = [None] # use length-1 list as a mutable

# later, in code:  
if __DBNAME__[0] is None:
    __DBNAME__[0] = name
55 xử lý các định dạng hộp thư cụ thể khác nhau.

Phương pháp là gì? ¶

Một phương thức là một hàm trên một số đối tượng

import foo
print(foo.X)  # prints 1
32 mà bạn thường gọi là
__DBNAME__ = [None] # use length-1 list as a mutable

# later, in code:  
if __DBNAME__[0] is None:
    __DBNAME__[0] = name
57. Các phương thức được định nghĩa là các hàm bên trong định nghĩa lớp:

>>> foo()
Traceback (most recent call last):
  ...
UnboundLocalError: local variable 'x' referenced before assignment
3

Bản thân là gì? ¶

Bản thân chỉ là một tên thông thường cho đối số đầu tiên của một phương thức. Một phương thức được định nghĩa là

__DBNAME__ = [None] # use length-1 list as a mutable

# later, in code:  
if __DBNAME__[0] is None:
    __DBNAME__[0] = name
58 nên được gọi là
__DBNAME__ = [None] # use length-1 list as a mutable

# later, in code:  
if __DBNAME__[0] is None:
    __DBNAME__[0] = name
59 cho một số trường hợp
import foo
print(foo.X)  # prints 1
32 của lớp trong đó định nghĩa xảy ra; Phương pháp được gọi sẽ nghĩ rằng nó được gọi là
__DBNAME__ = [None] # use length-1 list as a mutable

# later, in code:  
if __DBNAME__[0] is None:
    __DBNAME__[0] = name
61.

Xem thêm tại sao phải ’tự được sử dụng rõ ràng trong các định nghĩa và cuộc gọi phương thức ?.Why must ‘self’ be used explicitly in method definitions and calls?.

Làm cách nào để kiểm tra xem một đối tượng là một thể hiện của một lớp nhất định hoặc của một lớp con của nó? ¶

Sử dụng chức năng tích hợp

__DBNAME__ = [None] # use length-1 list as a mutable

# later, in code:  
if __DBNAME__[0] is None:
    __DBNAME__[0] = name
62. Bạn có thể kiểm tra xem một đối tượng có phải là một thể hiện của bất kỳ một số lớp nào bằng cách cung cấp một tuple thay vì một lớp duy nhất, ví dụ:
__DBNAME__ = [None] # use length-1 list as a mutable

# later, in code:  
if __DBNAME__[0] is None:
    __DBNAME__[0] = name
63, và cũng có thể kiểm tra xem một đối tượng có phải là một trong những loại tích hợp của Python hay không, ví dụ:
__DBNAME__ = [None] # use length-1 list as a mutable

# later, in code:  
if __DBNAME__[0] is None:
    __DBNAME__[0] = name
64 hoặc
__DBNAME__ = [None] # use length-1 list as a mutable

# later, in code:  
if __DBNAME__[0] is None:
    __DBNAME__[0] = name
65.

Lưu ý rằng

__DBNAME__ = [None] # use length-1 list as a mutable

# later, in code:  
if __DBNAME__[0] is None:
    __DBNAME__[0] = name
66 cũng kiểm tra kế thừa ảo từ một lớp cơ sở trừu tượng. Vì vậy, bài kiểm tra sẽ trả về
__DBNAME__ = [None] # use length-1 list as a mutable

# later, in code:  
if __DBNAME__[0] is None:
    __DBNAME__[0] = name
67 cho một lớp đã đăng ký ngay cả khi không được kế thừa trực tiếp hoặc gián tiếp từ nó. Để kiểm tra cho kế thừa thực sự, hãy quét MRO của lớp:abstract base class. So, the test will return
__DBNAME__ = [None] # use length-1 list as a mutable

# later, in code:  
if __DBNAME__[0] is None:
    __DBNAME__[0] = name
67 for a registered class even if hasn’t directly or indirectly inherited from it. To test for “true inheritance”, scan the MRO of the class:

>>> foo()
Traceback (most recent call last):
  ...
UnboundLocalError: local variable 'x' referenced before assignment
4

>>> foo()
Traceback (most recent call last):
  ...
UnboundLocalError: local variable 'x' referenced before assignment
5

Lưu ý rằng hầu hết các chương trình không sử dụng

__DBNAME__ = [None] # use length-1 list as a mutable

# later, in code:  
if __DBNAME__[0] is None:
    __DBNAME__[0] = name
66 trên các lớp do người dùng xác định rất thường xuyên. Nếu bạn đang tự phát triển các lớp, một kiểu hướng đối tượng phù hợp hơn là xác định các phương thức trên các lớp gói gọn một hành vi cụ thể, thay vì kiểm tra lớp đối tượng và làm một việc khác dựa trên lớp học. Ví dụ: nếu bạn có một chức năng làm điều gì đó:

>>> foo()
Traceback (most recent call last):
  ...
UnboundLocalError: local variable 'x' referenced before assignment
6

Một cách tiếp cận tốt hơn là xác định phương thức

__DBNAME__ = [None] # use length-1 list as a mutable

# later, in code:  
if __DBNAME__[0] is None:
    __DBNAME__[0] = name
69 trên tất cả các lớp và chỉ gọi nó:

>>> foo()
Traceback (most recent call last):
  ...
UnboundLocalError: local variable 'x' referenced before assignment
7

Đoàn là gì? ¶

Phái đoàn là một kỹ thuật định hướng đối tượng (còn được gọi là mẫu thiết kế). Hãy nói rằng bạn có một đối tượng

import foo
print(foo.X)  # prints 1
32 và muốn thay đổi hành vi chỉ là một trong các phương pháp của nó. Bạn có thể tạo một lớp mới cung cấp một triển khai mới của phương thức mà bạn quan tâm đến việc thay đổi và ủy thác tất cả các phương thức khác cho phương thức tương ứng của
import foo
print(foo.X)  # prints 1
32.

Các lập trình viên Python có thể dễ dàng thực hiện phái đoàn. Ví dụ: lớp sau thực hiện một lớp hoạt động giống như một tệp nhưng chuyển đổi tất cả dữ liệu bằng văn bản thành chữ hoa:

>>> foo()
Traceback (most recent call last):
  ...
UnboundLocalError: local variable 'x' referenced before assignment
8

Ở đây, lớp

__DBNAME__ = [None] # use length-1 list as a mutable

# later, in code:  
if __DBNAME__[0] is None:
    __DBNAME__[0] = name
72 xác định lại phương thức
__DBNAME__ = [None] # use length-1 list as a mutable

# later, in code:  
if __DBNAME__[0] is None:
    __DBNAME__[0] = name
73 để chuyển đổi chuỗi đối số thành chữ hoa trước khi gọi phương thức
__DBNAME__ = [None] # use length-1 list as a mutable

# later, in code:  
if __DBNAME__[0] is None:
    __DBNAME__[0] = name
74 bên dưới. Tất cả các phương pháp khác được giao cho đối tượng
__DBNAME__ = [None] # use length-1 list as a mutable

# later, in code:  
if __DBNAME__[0] is None:
    __DBNAME__[0] = name
75 cơ bản. Phái đoàn được thực hiện thông qua phương pháp
__DBNAME__ = [None] # use length-1 list as a mutable

# later, in code:  
if __DBNAME__[0] is None:
    __DBNAME__[0] = name
76; Tham khảo tài liệu tham khảo ngôn ngữ để biết thêm thông tin về việc kiểm soát quyền truy cập thuộc tính.the language reference for more information about controlling attribute access.

Lưu ý rằng đối với các trường hợp chung hơn, phái đoàn có thể trở nên khó khăn hơn. Khi các thuộc tính phải được đặt cũng như truy xuất, lớp cũng phải xác định phương thức

__DBNAME__ = [None] # use length-1 list as a mutable

# later, in code:  
if __DBNAME__[0] is None:
    __DBNAME__[0] = name
77 và nó phải làm như vậy một cách cẩn thận. Việc triển khai cơ bản của
__DBNAME__ = [None] # use length-1 list as a mutable

# later, in code:  
if __DBNAME__[0] is None:
    __DBNAME__[0] = name
77 gần như tương đương với các điều sau:

>>> foo()
Traceback (most recent call last):
  ...
UnboundLocalError: local variable 'x' referenced before assignment
9

Hầu hết các triển khai

__DBNAME__ = [None] # use length-1 list as a mutable

# later, in code:  
if __DBNAME__[0] is None:
    __DBNAME__[0] = name
77 phải sửa đổi
__DBNAME__ = [None] # use length-1 list as a mutable

# later, in code:  
if __DBNAME__[0] is None:
    __DBNAME__[0] = name
80 để lưu trữ trạng thái địa phương cho bản thân mà không gây ra đệ quy vô hạn.

Làm cách nào để gọi một phương thức được xác định trong một lớp cơ sở từ một lớp dẫn xuất mở rộng nó? ¶

Sử dụng chức năng

__DBNAME__ = [None] # use length-1 list as a mutable

# later, in code:  
if __DBNAME__[0] is None:
    __DBNAME__[0] = name
81 tích hợp:

>>> x = 10
>>> def foobar():
...     global x
...     print(x)
...     x += 1
>>> foobar()
10
0

Trong ví dụ,

__DBNAME__ = [None] # use length-1 list as a mutable

# later, in code:  
if __DBNAME__[0] is None:
    __DBNAME__[0] = name
81 sẽ tự động xác định phiên bản mà nó được gọi là (giá trị
__DBNAME__ = [None] # use length-1 list as a mutable

# later, in code:  
if __DBNAME__[0] is None:
    __DBNAME__[0] = name
83), hãy tìm thứ tự độ phân giải phương thức (MRO) với
__DBNAME__ = [None] # use length-1 list as a mutable

# later, in code:  
if __DBNAME__[0] is None:
    __DBNAME__[0] = name
84 và trả về dòng tiếp theo sau
__DBNAME__ = [None] # use length-1 list as a mutable

# later, in code:  
if __DBNAME__[0] is None:
    __DBNAME__[0] = name
85 trong MRO:
__DBNAME__ = [None] # use length-1 list as a mutable

# later, in code:  
if __DBNAME__[0] is None:
    __DBNAME__[0] = name
86.method resolution order (MRO) with
__DBNAME__ = [None] # use length-1 list as a mutable

# later, in code:  
if __DBNAME__[0] is None:
    __DBNAME__[0] = name
84, and return the next in line after
__DBNAME__ = [None] # use length-1 list as a mutable

# later, in code:  
if __DBNAME__[0] is None:
    __DBNAME__[0] = name
85 in the MRO:
__DBNAME__ = [None] # use length-1 list as a mutable

# later, in code:  
if __DBNAME__[0] is None:
    __DBNAME__[0] = name
86.

Làm cách nào để sắp xếp mã của mình để giúp thay đổi lớp cơ sở dễ dàng hơn? ¶

Bạn có thể gán lớp cơ sở cho một bí danh và xuất phát từ bí danh. Sau đó, tất cả những gì bạn phải thay đổi là giá trị được gán cho bí danh. Ngẫu nhiên, thủ thuật này cũng rất tiện dụng nếu bạn muốn quyết định một cách linh hoạt (ví dụ: tùy thuộc vào tính khả dụng của tài nguyên) sẽ sử dụng lớp cơ sở nào. Thí dụ:

>>> x = 10
>>> def foobar():
...     global x
...     print(x)
...     x += 1
>>> foobar()
10
1

Làm cách nào để tạo dữ liệu lớp tĩnh và phương thức lớp tĩnh? ¶

Cả dữ liệu tĩnh và phương pháp tĩnh (theo nghĩa C ++ hoặc Java) đều được hỗ trợ trong Python.

Đối với dữ liệu tĩnh, chỉ cần xác định một thuộc tính lớp. Để gán một giá trị mới cho thuộc tính, bạn phải sử dụng rõ ràng tên lớp trong bài tập:

>>> x = 10
>>> def foobar():
...     global x
...     print(x)
...     x += 1
>>> foobar()
10
2

__DBNAME__ = [None] # use length-1 list as a mutable

# later, in code:  
if __DBNAME__[0] is None:
    __DBNAME__[0] = name
87 cũng đề cập đến
__DBNAME__ = [None] # use length-1 list as a mutable

# later, in code:  
if __DBNAME__[0] is None:
    __DBNAME__[0] = name
88 cho bất kỳ
__DBNAME__ = [None] # use length-1 list as a mutable

# later, in code:  
if __DBNAME__[0] is None:
    __DBNAME__[0] = name
89 nào sao cho
__DBNAME__ = [None] # use length-1 list as a mutable

# later, in code:  
if __DBNAME__[0] is None:
    __DBNAME__[0] = name
90 giữ, trừ khi được ghi đè bởi chính
__DBNAME__ = [None] # use length-1 list as a mutable

# later, in code:  
if __DBNAME__[0] is None:
    __DBNAME__[0] = name
89 hoặc bởi một số lớp trên đường dẫn tìm kiếm cấp cơ sở từ
__DBNAME__ = [None] # use length-1 list as a mutable

# later, in code:  
if __DBNAME__[0] is None:
    __DBNAME__[0] = name
92 trở lại
__DBNAME__ = [None] # use length-1 list as a mutable

# later, in code:  
if __DBNAME__[0] is None:
    __DBNAME__[0] = name
93.

THẬN TRỌNG: Trong một phương thức của C, một bài tập như

__DBNAME__ = [None] # use length-1 list as a mutable

# later, in code:  
if __DBNAME__[0] is None:
    __DBNAME__[0] = name
94 tạo ra một ví dụ mới và không liên quan có tên là đếm đếm trong ________ 383. Tái tạo tên dữ liệu tĩnh lớp phải luôn chỉ định lớp cho dù bên trong phương thức hay không:

Phương pháp tĩnh là có thể:

>>> x = 10
>>> def foobar():
...     global x
...     print(x)
...     x += 1
>>> foobar()
10
3

Tuy nhiên, một cách đơn giản hơn nhiều để có được hiệu ứng của phương pháp tĩnh là thông qua hàm cấp độ mô-đun đơn giản:

>>> x = 10
>>> def foobar():
...     global x
...     print(x)
...     x += 1
>>> foobar()
10
4

Nếu mã của bạn được cấu trúc để xác định một lớp (hoặc phân cấp lớp liên quan chặt chẽ) cho mỗi mô -đun, điều này sẽ cung cấp các đóng gói mong muốn.

Làm thế nào tôi có thể quá tải các hàm tạo (hoặc phương pháp) trong Python? ¶

Câu trả lời này thực sự áp dụng cho tất cả các phương pháp, nhưng câu hỏi thường xuất hiện đầu tiên trong bối cảnh các nhà xây dựng.

Trong c ++ bạn viết

>>> x = 10
>>> def foobar():
...     global x
...     print(x)
...     x += 1
>>> foobar()
10
5

Trong Python, bạn phải viết một hàm tạo duy nhất để bắt tất cả các trường hợp bằng cách sử dụng các đối số mặc định. Ví dụ:

>>> x = 10
>>> def foobar():
...     global x
...     print(x)
...     x += 1
>>> foobar()
10
6

Điều này không hoàn toàn tương đương, nhưng đủ gần trong thực tế.

Bạn cũng có thể thử một danh sách đối số có độ dài thay đổi, ví dụ:

>>> x = 10
>>> def foobar():
...     global x
...     print(x)
...     x += 1
>>> foobar()
10
7

Cách tiếp cận tương tự hoạt động cho tất cả các định nghĩa phương pháp.

Tôi cố gắng sử dụng __spam và tôi gặp lỗi về _someclassname__spam.¶

Các tên biến với các dấu gạch dưới hàng đầu là có thể cung cấp một cách đơn giản nhưng hiệu quả để xác định các biến riêng của lớp. Bất kỳ định danh nào của mẫu

__DBNAME__ = [None] # use length-1 list as a mutable

# later, in code:  
if __DBNAME__[0] is None:
    __DBNAME__[0] = name
96 (ít nhất hai dấu gạch dưới hàng đầu, nhiều nhất là một dấu gạch dưới) được thay thế về mặt văn bản bằng
__DBNAME__ = [None] # use length-1 list as a mutable

# later, in code:  
if __DBNAME__[0] is None:
    __DBNAME__[0] = name
97, trong đó
__DBNAME__ = [None] # use length-1 list as a mutable

# later, in code:  
if __DBNAME__[0] is None:
    __DBNAME__[0] = name
98 là tên lớp hiện tại với bất kỳ dấu gạch dưới hàng đầu nào bị tước.

Điều này không đảm bảo quyền riêng tư: Người dùng bên ngoài vẫn có thể cố tình truy cập thuộc tính _ classname__spam và các giá trị riêng tư được hiển thị trong đối tượng

__DBNAME__ = [None] # use length-1 list as a mutable

# later, in code:  
if __DBNAME__[0] is None:
    __DBNAME__[0] = name
99. Nhiều lập trình viên Python không bao giờ bận tâm sử dụng tên biến riêng tư.

Lớp của tôi xác định __del__ nhưng nó không được gọi khi tôi xóa đối tượng.¶

Có một số lý do có thể cho điều này.

Câu lệnh DEL không nhất thiết phải gọi

class Box:
    pass

__m = Box()  # m will contain all module-level values
__m.dbname = None  # database name global in module

# later, in code:
if __m.dbname is None:
    __m.dbname = name
00 - nó chỉ đơn giản là giảm số lượng tham chiếu của đối tượng và nếu điều này đạt đến 0
class Box:
    pass

__m = Box()  # m will contain all module-level values
__m.dbname = None  # database name global in module

# later, in code:
if __m.dbname is None:
    __m.dbname = name
00 được gọi.

Nếu cấu trúc dữ liệu của bạn chứa các liên kết tròn (ví dụ: một cây nơi mỗi đứa trẻ có tham chiếu cha mẹ và mỗi cha mẹ có danh sách con), số lượng tham chiếu sẽ không bao giờ quay trở lại bằng không. Thỉnh thoảng, Python chạy một thuật toán để phát hiện các chu kỳ như vậy, nhưng bộ thu rác có thể chạy một thời gian sau khi tham chiếu cuối cùng về cấu trúc dữ liệu của bạn biến mất, do đó, phương thức

class Box:
    pass

__m = Box()  # m will contain all module-level values
__m.dbname = None  # database name global in module

# later, in code:
if __m.dbname is None:
    __m.dbname = name
00 của bạn có thể được gọi vào một thời gian ngẫu nhiên và ngẫu nhiên. Điều này là bất tiện nếu bạn đang cố gắng tái tạo một vấn đề. Tồi tệ hơn, thứ tự trong đó các phương thức đối tượng
class Box:
    pass

__m = Box()  # m will contain all module-level values
__m.dbname = None  # database name global in module

# later, in code:
if __m.dbname is None:
    __m.dbname = name
00 được thực thi là tùy ý. Bạn có thể chạy
class Box:
    pass

__m = Box()  # m will contain all module-level values
__m.dbname = None  # database name global in module

# later, in code:
if __m.dbname is None:
    __m.dbname = name
04 để buộc một bộ sưu tập, nhưng có những trường hợp bệnh lý trong đó các đối tượng sẽ không bao giờ được thu thập.

Mặc dù người thu thập chu kỳ, nhưng nó vẫn là một ý tưởng tốt để xác định phương thức

class Box:
    pass

__m = Box()  # m will contain all module-level values
__m.dbname = None  # database name global in module

# later, in code:
if __m.dbname is None:
    __m.dbname = name
05 rõ ràng trên các đối tượng được gọi bất cứ khi nào bạn thực hiện với chúng. Phương thức
class Box:
    pass

__m = Box()  # m will contain all module-level values
__m.dbname = None  # database name global in module

# later, in code:
if __m.dbname is None:
    __m.dbname = name
05 sau đó có thể xóa các thuộc tính đề cập đến các tiểu mục. Don Tiết gọi trực tiếp
class Box:
    pass

__m = Box()  # m will contain all module-level values
__m.dbname = None  # database name global in module

# later, in code:
if __m.dbname is None:
    __m.dbname = name
00 -
class Box:
    pass

__m = Box()  # m will contain all module-level values
__m.dbname = None  # database name global in module

# later, in code:
if __m.dbname is None:
    __m.dbname = name
00 nên gọi
class Box:
    pass

__m = Box()  # m will contain all module-level values
__m.dbname = None  # database name global in module

# later, in code:
if __m.dbname is None:
    __m.dbname = name
05 và
class Box:
    pass

__m = Box()  # m will contain all module-level values
__m.dbname = None  # database name global in module

# later, in code:
if __m.dbname is None:
    __m.dbname = name
05 sẽ đảm bảo rằng nó có thể được gọi nhiều lần cho cùng một đối tượng.

Một cách khác để tránh các tài liệu tham khảo theo chu kỳ là sử dụng mô -đun

class Box:
    pass

__m = Box()  # m will contain all module-level values
__m.dbname = None  # database name global in module

# later, in code:
if __m.dbname is None:
    __m.dbname = name
11, cho phép bạn trỏ đến các đối tượng mà không cần tăng số lượng tham chiếu của chúng. Ví dụ, các cấu trúc dữ liệu cây nên sử dụng các tài liệu tham khảo yếu cho các tài liệu tham khảo cha mẹ và anh chị em của họ (nếu chúng cần chúng!).

Cuối cùng, nếu phương thức

class Box:
    pass

__m = Box()  # m will contain all module-level values
__m.dbname = None  # database name global in module

# later, in code:
if __m.dbname is None:
    __m.dbname = name
00 của bạn tăng ngoại lệ, một thông báo cảnh báo được in thành
class Box:
    pass

__m = Box()  # m will contain all module-level values
__m.dbname = None  # database name global in module

# later, in code:
if __m.dbname is None:
    __m.dbname = name
13.

Làm cách nào để có được một danh sách tất cả các trường hợp của một lớp nhất định? ¶

Python không theo dõi tất cả các trường hợp của một lớp (hoặc loại tích hợp). Bạn có thể lập trình trình xây dựng lớp lớp để theo dõi tất cả các trường hợp bằng cách giữ một danh sách các tài liệu tham khảo yếu cho từng trường hợp.

Tại sao kết quả của def initDB(name): global __DBNAME__ # add this line! if __DBNAME__ is None: # see notes below; explicit test for None __DBNAME__ = name else: raise RuntimeError("Database name has already been set.") 28 dường như không phải là duy nhất? ¶

def initDB(name):
    global __DBNAME__  # add this line!
    if __DBNAME__ is None: # see notes below; explicit test for None
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")
28 tích hợp trả về một số nguyên được đảm bảo là duy nhất trong suốt vòng đời của đối tượng. Vì ở Cpython, đây là địa chỉ bộ nhớ của đối tượng, điều này thường xảy ra sau khi một đối tượng bị xóa khỏi bộ nhớ, đối tượng mới được tạo tiếp theo được phân bổ ở cùng một vị trí trong bộ nhớ. Điều này được minh họa bằng ví dụ này:

>>> x = 10
>>> def foobar():
...     global x
...     print(x)
...     x += 1
>>> foobar()
10
8

Hai ID thuộc về các đối tượng số nguyên khác nhau được tạo trước đó và xóa ngay sau khi thực hiện cuộc gọi

def initDB(name):
    global __DBNAME__  # add this line!
    if __DBNAME__ is None: # see notes below; explicit test for None
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")
28. Để chắc chắn rằng các đối tượng có ID mà bạn muốn kiểm tra vẫn còn sống, hãy tạo một tham chiếu khác cho đối tượng:

>>> x = 10
>>> def foobar():
...     global x
...     print(x)
...     x += 1
>>> foobar()
10
9

Khi nào tôi có thể dựa vào các bài kiểm tra danh tính với toán tử IS? ¶

Các thử nghiệm toán tử

def initDB(name):
    global __DBNAME__  # add this line!
    if __DBNAME__ is None: # see notes below; explicit test for None
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")
27 cho nhận dạng đối tượng. Thử nghiệm
class Box:
    pass

__m = Box()  # m will contain all module-level values
__m.dbname = None  # database name global in module

# later, in code:
if __m.dbname is None:
    __m.dbname = name
18 tương đương với
class Box:
    pass

__m = Box()  # m will contain all module-level values
__m.dbname = None  # database name global in module

# later, in code:
if __m.dbname is None:
    __m.dbname = name
19.

Thuộc tính quan trọng nhất của kiểm tra danh tính là một đối tượng luôn giống hệt với chính nó,

class Box:
    pass

__m = Box()  # m will contain all module-level values
__m.dbname = None  # database name global in module

# later, in code:
if __m.dbname is None:
    __m.dbname = name
20 luôn trả về
__DBNAME__ = [None] # use length-1 list as a mutable

# later, in code:  
if __DBNAME__[0] is None:
    __DBNAME__[0] = name
67. Kiểm tra danh tính thường nhanh hơn các bài kiểm tra bình đẳng. Và không giống như các bài kiểm tra bình đẳng, các bài kiểm tra nhận dạng được đảm bảo sẽ trả về Boolean
__DBNAME__ = [None] # use length-1 list as a mutable

# later, in code:  
if __DBNAME__[0] is None:
    __DBNAME__[0] = name
67 hoặc
class Box:
    pass

__m = Box()  # m will contain all module-level values
__m.dbname = None  # database name global in module

# later, in code:
if __m.dbname is None:
    __m.dbname = name
23.

Tuy nhiên, các bài kiểm tra nhận dạng chỉ có thể được thay thế cho các bài kiểm tra bình đẳng khi nhận dạng đối tượng được đảm bảo. Nói chung, có ba trường hợp được đảm bảo danh tính:

1) Bài tập tạo tên mới nhưng không thay đổi danh tính đối tượng. Sau khi chuyển nhượng

class Box:
    pass

__m = Box()  # m will contain all module-level values
__m.dbname = None  # database name global in module

# later, in code:
if __m.dbname is None:
    __m.dbname = name
24, nó được đảm bảo rằng
class Box:
    pass

__m = Box()  # m will contain all module-level values
__m.dbname = None  # database name global in module

# later, in code:
if __m.dbname is None:
    __m.dbname = name
25.

2) Đặt một đối tượng vào một thùng chứa lưu trữ tham chiếu đối tượng không thay đổi nhận dạng đối tượng. Sau khi gán danh sách

class Box:
    pass

__m = Box()  # m will contain all module-level values
__m.dbname = None  # database name global in module

# later, in code:
if __m.dbname is None:
    __m.dbname = name
26, nó được đảm bảo rằng
class Box:
    pass

__m = Box()  # m will contain all module-level values
__m.dbname = None  # database name global in module

# later, in code:
if __m.dbname is None:
    __m.dbname = name
27.

3) Nếu một đối tượng là singleton, điều đó có nghĩa là chỉ có một trường hợp của đối tượng đó có thể tồn tại. Sau các bài tập

class Box:
    pass

__m = Box()  # m will contain all module-level values
__m.dbname = None  # database name global in module

# later, in code:
if __m.dbname is None:
    __m.dbname = name
28 và
class Box:
    pass

__m = Box()  # m will contain all module-level values
__m.dbname = None  # database name global in module

# later, in code:
if __m.dbname is None:
    __m.dbname = name
29, người ta đảm bảo rằng
class Box:
    pass

__m = Box()  # m will contain all module-level values
__m.dbname = None  # database name global in module

# later, in code:
if __m.dbname is None:
    __m.dbname = name
18 vì
import foo
print(foo.X)  # prints 1
70 là một singleton.

Trong hầu hết các trường hợp khác, các bài kiểm tra danh tính là không thể chấp nhận được và các bài kiểm tra bình đẳng được ưu tiên. Cụ thể, không nên sử dụng các bài kiểm tra nhận dạng để kiểm tra các hằng số như

def initDB(name):
    global __DBNAME__  # add this line!
    if __DBNAME__ is None: # see notes below; explicit test for None
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")
25 và
def initDB(name):
    global __DBNAME__  # add this line!
    if __DBNAME__ is None: # see notes below; explicit test for None
        __DBNAME__ = name
    else:
        raise RuntimeError("Database name has already been set.")
24 mà aren đảm bảo là singletons:

>>> def foo():
...    x = 10
...    def bar():
...        nonlocal x
...        print(x)
...        x += 1
...    bar()
...    print(x)
>>> foo()
10
11
0

Tương tự như vậy, các trường hợp mới của các thùng chứa có thể thay đổi không bao giờ giống hệt nhau:

>>> def foo():
...    x = 10
...    def bar():
...        nonlocal x
...        print(x)
...        x += 1
...    bar()
...    print(x)
>>> foo()
10
11
1

Trong mã thư viện tiêu chuẩn, bạn sẽ thấy một số mẫu phổ biến để sử dụng chính xác các bài kiểm tra nhận dạng:

1) Theo khuyến nghị của PEP 8, kiểm tra nhận dạng là cách ưa thích để kiểm tra

import foo
print(foo.X)  # prints 1
70. Điều này đọc giống như tiếng Anh đơn giản trong mã và tránh sự nhầm lẫn với các đối tượng khác có thể có các giá trị boolean đánh giá sai.PEP 8, an identity test is the preferred way to check for
import foo
print(foo.X)  # prints 1
70. This reads like plain English in code and avoids confusion with other objects that may have boolean values that evaluate to false.

2) Phát hiện các đối số tùy chọn có thể khó khăn khi

import foo
print(foo.X)  # prints 1
70 là giá trị đầu vào hợp lệ. Trong những tình huống đó, bạn có thể tạo một đối tượng Singleton Sentinel được đảm bảo là khác biệt với các đối tượng khác. Ví dụ, đây là cách thực hiện một phương pháp hoạt động như
class Box:
    pass

__m = Box()  # m will contain all module-level values
__m.dbname = None  # database name global in module

# later, in code:
if __m.dbname is None:
    __m.dbname = name
36:

>>> def foo():
...    x = 10
...    def bar():
...        nonlocal x
...        print(x)
...        x += 1
...    bar()
...    print(x)
>>> foo()
10
11
2

3) Việc triển khai container đôi khi cần tăng cường các bài kiểm tra bình đẳng với các bài kiểm tra nhận dạng. Điều này ngăn mã bị nhầm lẫn bởi các đối tượng như

class Box:
    pass

__m = Box()  # m will contain all module-level values
__m.dbname = None  # database name global in module

# later, in code:
if __m.dbname is None:
    __m.dbname = name
37 không bằng chính chúng.

Ví dụ: đây là việc triển khai

class Box:
    pass

__m = Box()  # m will contain all module-level values
__m.dbname = None  # database name global in module

# later, in code:
if __m.dbname is None:
    __m.dbname = name
38:

>>> def foo():
...    x = 10
...    def bar():
...        nonlocal x
...        print(x)
...        x += 1
...    bar()
...    print(x)
>>> foo()
10
11
3

Làm thế nào một lớp con có thể kiểm soát dữ liệu nào được lưu trữ trong một trường hợp bất biến? ¶

Khi phân lớp một loại bất biến, ghi đè phương thức

class Box:
    pass

__m = Box()  # m will contain all module-level values
__m.dbname = None  # database name global in module

# later, in code:
if __m.dbname is None:
    __m.dbname = name
39 thay vì phương thức
class Box:
    pass

__m = Box()  # m will contain all module-level values
__m.dbname = None  # database name global in module

# later, in code:
if __m.dbname is None:
    __m.dbname = name
40. Cái sau chỉ chạy sau một phiên bản được tạo, quá muộn để thay đổi dữ liệu trong một trường hợp bất biến.

Tất cả các lớp bất biến này có một chữ ký khác với lớp cha mẹ của họ:

>>> def foo():
...    x = 10
...    def bar():
...        nonlocal x
...        print(x)
...        x += 1
...    bar()
...    print(x)
>>> foo()
10
11
4

Các lớp có thể được sử dụng như thế này:

>>> def foo():
...    x = 10
...    def bar():
...        nonlocal x
...        print(x)
...        x += 1
...    bar()
...    print(x)
>>> foo()
10
11
5

Làm cách nào để gọi bộ nhớ cache? ¶

Hai công cụ chính cho các phương pháp bộ đệm là

class Box:
    pass

__m = Box()  # m will contain all module-level values
__m.dbname = None  # database name global in module

# later, in code:
if __m.dbname is None:
    __m.dbname = name
41 và
class Box:
    pass

__m = Box()  # m will contain all module-level values
__m.dbname = None  # database name global in module

# later, in code:
if __m.dbname is None:
    __m.dbname = name
42. Các cửa hàng trước kết quả ở cấp độ và trường hợp sau ở cấp lớp.

Cách tiếp cận bộ nhớ cache_property chỉ hoạt động với các phương thức không có bất kỳ đối số nào. Nó không tạo ra một tham chiếu đến thể hiện. Kết quả phương pháp được lưu trong bộ nhớ cache sẽ chỉ được giữ miễn là ví dụ còn sống.

Ưu điểm là khi một thể hiện không còn được sử dụng, kết quả phương thức được lưu trong bộ nhớ cache sẽ được phát hành ngay lập tức. Nhược điểm là nếu các trường hợp tích lũy, thì phương pháp tích lũy cũng sẽ kết quả. Chúng có thể phát triển mà không bị ràng buộc.

Phương pháp tiếp cận LRU_CACHE hoạt động với các phương pháp có các đối số có thể băm. Nó tạo ra một tham chiếu đến ví dụ trừ khi những nỗ lực đặc biệt được thực hiện để vượt qua trong các tài liệu tham khảo yếu.

Ưu điểm của thuật toán ít được sử dụng gần đây là bộ đệm được giới hạn bởi mức tối đa được chỉ định. Nhược điểm là các trường hợp được giữ sống cho đến khi chúng ra khỏi bộ đệm hoặc cho đến khi bộ đệm được xóa.

Ví dụ này cho thấy các kỹ thuật khác nhau:

>>> def foo():
...    x = 10
...    def bar():
...        nonlocal x
...        print(x)
...        x += 1
...    bar()
...    print(x)
>>> foo()
10
11
6

Ví dụ trên giả định rằng Station_id không bao giờ thay đổi. Nếu các thuộc tính thể hiện có liên quan có thể thay đổi, phương pháp lưu trữ_property có thể được thực hiện để hoạt động vì nó không thể phát hiện các thay đổi đối với các thuộc tính.

Cách tiếp cận LRU_CACHE có thể được thực hiện để hoạt động, nhưng lớp cần xác định các phương thức __eq__ và __hash__ để bộ đệm có thể phát hiện các bản cập nhật thuộc tính có liên quan:

>>> def foo():
...    x = 10
...    def bar():
...        nonlocal x
...        print(x)
...        x += 1
...    bar()
...    print(x)
>>> foo()
10
11
7

Mô -đun bình

Làm cách nào để tạo tệp .pyc? ¶

Khi một mô -đun được nhập lần đầu tiên (hoặc khi tệp nguồn đã thay đổi kể từ khi tệp được biên dịch hiện tại được tạo), tệp

class Box:
    pass

__m = Box()  # m will contain all module-level values
__m.dbname = None  # database name global in module

# later, in code:
if __m.dbname is None:
    __m.dbname = name
43 chứa mã được biên dịch sẽ được tạo trong thư mục con
class Box:
    pass

__m = Box()  # m will contain all module-level values
__m.dbname = None  # database name global in module

# later, in code:
if __m.dbname is None:
    __m.dbname = name
44 của thư mục chứa tệp
class Box:
    pass

__m = Box()  # m will contain all module-level values
__m.dbname = None  # database name global in module

# later, in code:
if __m.dbname is None:
    __m.dbname = name
45. Tệp
class Box:
    pass

__m = Box()  # m will contain all module-level values
__m.dbname = None  # database name global in module

# later, in code:
if __m.dbname is None:
    __m.dbname = name
43 sẽ có tên tệp bắt đầu với cùng tên với tệp
class Box:
    pass

__m = Box()  # m will contain all module-level values
__m.dbname = None  # database name global in module

# later, in code:
if __m.dbname is None:
    __m.dbname = name
45 và kết thúc bằng
class Box:
    pass

__m = Box()  # m will contain all module-level values
__m.dbname = None  # database name global in module

# later, in code:
if __m.dbname is None:
    __m.dbname = name
43, với thành phần giữa phụ thuộc vào nhị phân
class Box:
    pass

__m = Box()  # m will contain all module-level values
__m.dbname = None  # database name global in module

# later, in code:
if __m.dbname is None:
    __m.dbname = name
49 cụ thể đã tạo ra nó. (Xem PEP 3147 để biết chi tiết.)PEP 3147 for details.)

Một lý do mà một tệp

class Box:
    pass

__m = Box()  # m will contain all module-level values
__m.dbname = None  # database name global in module

# later, in code:
if __m.dbname is None:
    __m.dbname = name
43 không thể được tạo là một vấn đề về quyền với thư mục chứa tệp nguồn, có nghĩa là không thể tạo thư mục con
class Box:
    pass

__m = Box()  # m will contain all module-level values
__m.dbname = None  # database name global in module

# later, in code:
if __m.dbname is None:
    __m.dbname = name
44. Điều này có thể xảy ra, ví dụ, nếu bạn phát triển như một người dùng nhưng chạy như một người dùng khác, chẳng hạn như nếu bạn đang thử nghiệm với một máy chủ web.

Trừ khi biến môi trường

class Box:
    pass

__m = Box()  # m will contain all module-level values
__m.dbname = None  # database name global in module

# later, in code:
if __m.dbname is None:
    __m.dbname = name
52 được đặt, việc tạo tệp .pyc sẽ tự động nếu bạn nhập mô -đun và Python có khả năng (quyền, không gian trống, v.v.) .
class Box:
    pass

__m = Box()  # m will contain all module-level values
__m.dbname = None  # database name global in module

# later, in code:
if __m.dbname is None:
    __m.dbname = name
52 environment variable is set, creation of a .pyc file is automatic if you’re importing a module and Python has the ability (permissions, free space, etc…) to create a
class Box:
    pass

__m = Box()  # m will contain all module-level values
__m.dbname = None  # database name global in module

# later, in code:
if __m.dbname is None:
    __m.dbname = name
44 subdirectory and write the compiled module to that subdirectory.

Chạy Python trên một tập lệnh cấp cao nhất không được coi là nhập và không có

class Box:
    pass

__m = Box()  # m will contain all module-level values
__m.dbname = None  # database name global in module

# later, in code:
if __m.dbname is None:
    __m.dbname = name
43 sẽ được tạo. Ví dụ: nếu bạn có mô-đun cấp cao nhất
class Box:
    pass

__m = Box()  # m will contain all module-level values
__m.dbname = None  # database name global in module

# later, in code:
if __m.dbname is None:
    __m.dbname = name
55 nhập mô-đun khác
class Box:
    pass

__m = Box()  # m will contain all module-level values
__m.dbname = None  # database name global in module

# later, in code:
if __m.dbname is None:
    __m.dbname = name
56, khi bạn chạy
class Box:
    pass

__m = Box()  # m will contain all module-level values
__m.dbname = None  # database name global in module

# later, in code:
if __m.dbname is None:
    __m.dbname = name
57 (bằng cách nhập
class Box:
    pass

__m = Box()  # m will contain all module-level values
__m.dbname = None  # database name global in module

# later, in code:
if __m.dbname is None:
    __m.dbname = name
58 dưới dạng lệnh shell), sẽ được tạo cho
class Box:
    pass

__m = Box()  # m will contain all module-level values
__m.dbname = None  # database name global in module

# later, in code:
if __m.dbname is None:
    __m.dbname = name
60 vì
class Box:
    pass

__m = Box()  # m will contain all module-level values
__m.dbname = None  # database name global in module

# later, in code:
if __m.dbname is None:
    __m.dbname = name
60 Được tạo cho
class Box:
    pass

__m = Box()  # m will contain all module-level values
__m.dbname = None  # database name global in module

# later, in code:
if __m.dbname is None:
    __m.dbname = name
57 kể từ khi
class Box:
    pass

__m = Box()  # m will contain all module-level values
__m.dbname = None  # database name global in module

# later, in code:
if __m.dbname is None:
    __m.dbname = name
55 không được nhập.

Nếu bạn cần tạo tệp

class Box:
    pass

__m = Box()  # m will contain all module-level values
__m.dbname = None  # database name global in module

# later, in code:
if __m.dbname is None:
    __m.dbname = name
43 cho
class Box:
    pass

__m = Box()  # m will contain all module-level values
__m.dbname = None  # database name global in module

# later, in code:
if __m.dbname is None:
    __m.dbname = name
57 - nghĩa là tạo tệp
class Box:
    pass

__m = Box()  # m will contain all module-level values
__m.dbname = None  # database name global in module

# later, in code:
if __m.dbname is None:
    __m.dbname = name
43 cho một mô -đun không được nhập - bạn có thể, sử dụng các mô -đun
class Box:
    pass

__m = Box()  # m will contain all module-level values
__m.dbname = None  # database name global in module

# later, in code:
if __m.dbname is None:
    __m.dbname = name
68 và
class Box:
    pass

__m = Box()  # m will contain all module-level values
__m.dbname = None  # database name global in module

# later, in code:
if __m.dbname is None:
    __m.dbname = name
69.

Mô -đun

class Box:
    pass

__m = Box()  # m will contain all module-level values
__m.dbname = None  # database name global in module

# later, in code:
if __m.dbname is None:
    __m.dbname = name
68 có thể biên dịch thủ công bất kỳ mô -đun nào. Một cách là sử dụng hàm
class Box:
    pass

__m = Box()  # m will contain all module-level values
__m.dbname = None  # database name global in module

# later, in code:
if __m.dbname is None:
    __m.dbname = name
71 trong mô -đun đó một cách tương tác:

>>> def foo():
...    x = 10
...    def bar():
...        nonlocal x
...        print(x)
...        x += 1
...    bar()
...    print(x)
>>> foo()
10
11
8

Điều này sẽ ghi

class Box:
    pass

__m = Box()  # m will contain all module-level values
__m.dbname = None  # database name global in module

# later, in code:
if __m.dbname is None:
    __m.dbname = name
43 vào thư mục con
class Box:
    pass

__m = Box()  # m will contain all module-level values
__m.dbname = None  # database name global in module

# later, in code:
if __m.dbname is None:
    __m.dbname = name
44 ở cùng một vị trí với
class Box:
    pass

__m = Box()  # m will contain all module-level values
__m.dbname = None  # database name global in module

# later, in code:
if __m.dbname is None:
    __m.dbname = name
55 (hoặc bạn có thể ghi đè nó với tham số tùy chọn
class Box:
    pass

__m = Box()  # m will contain all module-level values
__m.dbname = None  # database name global in module

# later, in code:
if __m.dbname is None:
    __m.dbname = name
75).

Bạn cũng có thể tự động biên dịch tất cả các tệp trong thư mục hoặc thư mục bằng mô -đun

class Box:
    pass

__m = Box()  # m will contain all module-level values
__m.dbname = None  # database name global in module

# later, in code:
if __m.dbname is None:
    __m.dbname = name
69. Bạn có thể làm điều đó từ dấu nhắc Shell bằng cách chạy
class Box:
    pass

__m = Box()  # m will contain all module-level values
__m.dbname = None  # database name global in module

# later, in code:
if __m.dbname is None:
    __m.dbname = name
77 và cung cấp đường dẫn của thư mục chứa các tệp Python để biên dịch:

Làm cách nào để tìm tên mô -đun hiện tại? ¶

Một mô -đun có thể tìm ra tên mô -đun của riêng mình bằng cách xem biến toàn cầu được xác định trước

class Box:
    pass

__m = Box()  # m will contain all module-level values
__m.dbname = None  # database name global in module

# later, in code:
if __m.dbname is None:
    __m.dbname = name
78. Nếu điều này có giá trị
class Box:
    pass

__m = Box()  # m will contain all module-level values
__m.dbname = None  # database name global in module

# later, in code:
if __m.dbname is None:
    __m.dbname = name
79, chương trình đang chạy dưới dạng tập lệnh. Nhiều mô-đun thường được sử dụng bằng cách nhập chúng cũng cung cấp giao diện dòng lệnh hoặc tự kiểm tra và chỉ thực thi mã này sau khi kiểm tra
class Box:
    pass

__m = Box()  # m will contain all module-level values
__m.dbname = None  # database name global in module

# later, in code:
if __m.dbname is None:
    __m.dbname = name
78:

>>> def foo():
...    x = 10
...    def bar():
...        nonlocal x
...        print(x)
...        x += 1
...    bar()
...    print(x)
>>> foo()
10
11
9

Làm thế nào tôi có thể có các mô -đun nhập cùng nhau? ¶

Giả sử bạn có các mô -đun sau:

class Box:
    pass

__m = Box()  # m will contain all module-level values
__m.dbname = None  # database name global in module

# later, in code:
if __m.dbname is None:
    __m.dbname = name
55:

import foo
print(foo.X)  # prints 1
00

class Box:
    pass

__m = Box()  # m will contain all module-level values
__m.dbname = None  # database name global in module

# later, in code:
if __m.dbname is None:
    __m.dbname = name
82:

import foo
print(foo.X)  # prints 1
01

Vấn đề là trình thông dịch sẽ thực hiện các bước sau:

  • Nhập khẩu chính

    class Box:
        pass
    
    __m = Box()  # m will contain all module-level values
    __m.dbname = None  # database name global in module
    
    # later, in code:
    if __m.dbname is None:
        __m.dbname = name
    
    57

  • Quả cầu trống cho

    class Box:
        pass
    
    __m = Box()  # m will contain all module-level values
    __m.dbname = None  # database name global in module
    
    # later, in code:
    if __m.dbname is None:
        __m.dbname = name
    
    57 được tạo

  • class Box:
        pass
    
    __m = Box()  # m will contain all module-level values
    __m.dbname = None  # database name global in module
    
    # later, in code:
    if __m.dbname is None:
        __m.dbname = name
    
    57 được biên dịch và bắt đầu thực thi

  • class Box:
        pass
    
    __m = Box()  # m will contain all module-level values
    __m.dbname = None  # database name global in module
    
    # later, in code:
    if __m.dbname is None:
        __m.dbname = name
    
    57 Nhập khẩu
    class Box:
        pass
    
    __m = Box()  # m will contain all module-level values
    __m.dbname = None  # database name global in module
    
    # later, in code:
    if __m.dbname is None:
        __m.dbname = name
    
    87

  • Quả cầu trống cho

    class Box:
        pass
    
    __m = Box()  # m will contain all module-level values
    __m.dbname = None  # database name global in module
    
    # later, in code:
    if __m.dbname is None:
        __m.dbname = name
    
    87 được tạo ra

  • class Box:
        pass
    
    __m = Box()  # m will contain all module-level values
    __m.dbname = None  # database name global in module
    
    # later, in code:
    if __m.dbname is None:
        __m.dbname = name
    
    87 được biên dịch và bắt đầu thực thi

  • class Box:
        pass
    
    __m = Box()  # m will contain all module-level values
    __m.dbname = None  # database name global in module
    
    # later, in code:
    if __m.dbname is None:
        __m.dbname = name
    
    87 Nhập khẩu
    class Box:
        pass
    
    __m = Box()  # m will contain all module-level values
    __m.dbname = None  # database name global in module
    
    # later, in code:
    if __m.dbname is None:
        __m.dbname = name
    
    57 (đây là một không có vì đã có một mô-đun có tên
    class Box:
        pass
    
    __m = Box()  # m will contain all module-level values
    __m.dbname = None  # database name global in module
    
    # later, in code:
    if __m.dbname is None:
        __m.dbname = name
    
    57)

  • Cơ chế nhập khẩu cố gắng đọc

    class Box:
        pass
    
    __m = Box()  # m will contain all module-level values
    __m.dbname = None  # database name global in module
    
    # later, in code:
    if __m.dbname is None:
        __m.dbname = name
    
    93 từ
    class Box:
        pass
    
    __m = Box()  # m will contain all module-level values
    __m.dbname = None  # database name global in module
    
    # later, in code:
    if __m.dbname is None:
        __m.dbname = name
    
    57 Globals, để đặt
    class Box:
        pass
    
    __m = Box()  # m will contain all module-level values
    __m.dbname = None  # database name global in module
    
    # later, in code:
    if __m.dbname is None:
        __m.dbname = name
    
    95

Bước cuối cùng thất bại, bởi vì Python đã được thực hiện với việc diễn giải

class Box:
    pass

__m = Box()  # m will contain all module-level values
__m.dbname = None  # database name global in module

# later, in code:
if __m.dbname is None:
    __m.dbname = name
57 và từ điển biểu tượng toàn cầu cho
class Box:
    pass

__m = Box()  # m will contain all module-level values
__m.dbname = None  # database name global in module

# later, in code:
if __m.dbname is None:
    __m.dbname = name
57 vẫn còn trống.

Điều tương tự cũng xảy ra khi bạn sử dụng

class Box:
    pass

__m = Box()  # m will contain all module-level values
__m.dbname = None  # database name global in module

# later, in code:
if __m.dbname is None:
    __m.dbname = name
98, và sau đó cố gắng truy cập
class Box:
    pass

__m = Box()  # m will contain all module-level values
__m.dbname = None  # database name global in module

# later, in code:
if __m.dbname is None:
    __m.dbname = name
99 trong mã toàn cầu.

Có (ít nhất) ba cách giải quyết có thể cho vấn đề này.

Guido Van Rossum khuyên bạn nên tránh mọi việc sử dụng

>>> x = 10
>>> def bar():
...     print(x)
>>> bar()
10
00 và đặt tất cả các mã bên trong các chức năng. Khởi tạo các biến toàn cầu và biến lớp nên chỉ sử dụng các hằng số hoặc các hàm tích hợp. Điều này có nghĩa là tất cả mọi thứ từ một mô -đun nhập khẩu được tham chiếu là
>>> x = 10
>>> def bar():
...     print(x)
>>> bar()
10
01.

Jim Roskind đề nghị thực hiện các bước theo thứ tự sau trong mỗi mô -đun:

  • Xuất khẩu (toàn cầu, chức năng và các lớp mà không cần các lớp cơ sở nhập khẩu)

  • >>> x = 10
    >>> def bar():
    ...     print(x)
    >>> bar()
    10
    
    02 Báo cáo

  • Mã hoạt động (bao gồm cả các toàn cầu được khởi tạo từ các giá trị đã nhập).

Van Rossum không thích cách tiếp cận này nhiều vì hàng nhập khẩu xuất hiện ở một nơi kỳ lạ, nhưng nó hoạt động.

Matthias Urlichs khuyến nghị tái cấu trúc mã của bạn để nhập khẩu đệ quy là không cần thiết ngay từ đầu.

Những giải pháp này không loại trừ lẫn nhau.

__Import __ (‘X.Y.Z,) trả về; Làm thế nào để tôi có được z? ¶

Thay vào đó, hãy xem xét sử dụng chức năng tiện lợi

>>> x = 10
>>> def bar():
...     print(x)
>>> bar()
10
03 từ
>>> x = 10
>>> def bar():
...     print(x)
>>> bar()
10
04:

import foo
print(foo.X)  # prints 1
02

Khi tôi chỉnh sửa một mô -đun nhập khẩu và kể lại nó, các thay đổi don don hiển thị. Lý do tại sao điều này xảy ra?¶

Vì lý do hiệu quả cũng như tính nhất quán, Python chỉ đọc tệp mô -đun lần đầu tiên một mô -đun được nhập. Nếu nó không thành công, trong một chương trình bao gồm nhiều mô-đun trong đó mỗi mô-đun nhập cùng một mô-đun cơ bản, mô-đun cơ bản sẽ được phân tích cú pháp và phân tích lại nhiều lần. Để buộc đọc lại một mô-đun đã thay đổi, hãy làm điều này:

import foo
print(foo.X)  # prints 1
03

CẢNH BÁO: Kỹ thuật này không phải là 100% chống lừa. Cụ thể, các mô -đun chứa các câu như

import foo
print(foo.X)  # prints 1
04

sẽ tiếp tục làm việc với phiên bản cũ của các đối tượng nhập khẩu. Nếu mô -đun chứa các định nghĩa lớp, các phiên bản lớp hiện tại sẽ không được cập nhật để sử dụng định nghĩa lớp mới. Điều này có thể dẫn đến hành vi nghịch lý sau:

import foo
print(foo.X)  # prints 1
05

Bản chất của vấn đề được làm rõ nếu bạn in ra danh tính của các đối tượng của lớp:

import foo
print(foo.X)  # prints 1
06

Làm thế nào để bạn tạo một biến mô -đun trong Python?

Làm thế nào để tạo một biến toàn cầu..
Tạo một mô -đun toàn cầu. #Global.py current_value = 0 ..
Tạo một tệp chương trình Python để truy cập biến toàn cầu. #Updater.py Nhập toàn cầu def update_value (): Global.Current_Value = 100 ..
Tạo một chương trình Python khác để kiểm tra giá trị có được thay đổi hay không ..

Các biến mô -đun là gì?

Một biến cấp độ mô-đun được khai báo cho một mô-đun cụ thể.Nó có sẵn cho tất cả các thủ tục trong mô -đun đó nhưng không phải là phần còn lại của ứng dụng.Các biến cấp độ mô-đun vẫn tồn tại trong thời gian tồn tại của ứng dụng và bảo tồn các giá trị của chúng.declared for a particular module. It is available to all procedures within that module but not to the rest of the application. Module-level variables remain in existence for the lifetime of the application and preserve their values.

Làm cách nào để sử dụng một biến từ một mô -đun khác trong Python?

Để nhập các biến từ một tệp khác, chúng tôi phải nhập tệp đó từ chương trình hiện tại ...
Nhập và sau đó sử dụng.để truy cập biến ..
từ nhập và sử dụng các biến ..
từ nhập * và sau đó sử dụng các biến trực tiếp ..

Làm thế nào để bạn xác định một mô -đun

Bạn không thể tham gia lại các biến cấp độ mô-đun bên trong hàm Python ...
Hai dấu gạch dưới hàng đầu sẽ dẫn đến việc mang tên Mangling.....
Liên quan đến lớp hộp, sẽ không tốt hơn để xác định dbname = không có trong hàm init hơn là bên ngoài, như trong ví dụ?....
Python không quan tâm làm thế nào các biến được thiết lập ..