Sự khác biệt giữa các phương thức trong Python - Sự khác biệt giữa một hàm, một phương thức không liên kết và một phương thức bị ràng buộc là gì? Đọc và ghi tệp. Phép toán và toán hạng

Tổng quan về sự khác biệt cú pháp giữa python2 và python3.

In - chức năng

Câu lệnh print đã được thay thế bằng hàm print (), với các đối số được đặt tên để thay thế hầu hết cú pháp của câu lệnh print cũ. Ví dụ:

Python2: print "Câu trả lời là", 2 * 2 Python3: print ("Câu trả lời là", 2 * 2) Python2: print x, # Dấu phẩy ở cuối ngăn chặn nguồn cấp dữ liệu dòng Python3: print (x, end = "") # Thêm một khoảng trắng thay vì một dòng mới Python2: in # In nguồn cấp dòng Python3: print () # Bạn cần gọi hàm! Python2: print >> sys. stderr, "lỗi nghiêm trọng" Python3: print ("lỗi nghiêm trọng", tệp = sys. stderr) Python2: print (x, y) # In repr ((x, y)) Python3: print ((x, y)) # Không được nhầm lẫn với print (x, y)!

Ngoài ra, bạn có thể tùy chỉnh dấu phân cách giữa các phần tử, ví dụ:

>>> print ("Có<" , 2 ** 32 , ">khả năng! ", sep =" ") Có<4294967296>khả năng!

Hàm print () không hỗ trợ tính năng "khoảng trắng mềm" của câu lệnh in cũ. Ví dụ: trong Python 2, in "A \ n", "B" sẽ in "A \ nB \ n"; nhưng trong Python 3, print ("A \ n", "B") sẽ in ra "A \ n B \ n".

Bản đồ và trình lặp thay vì danh sách

Một số phương thức nổi tiếng không trả về trong Python 3:

  • Các phương thức từ điển dict.keys (), dict.items () và dict.values ​​() trả về "chế độ xem" thay vì danh sách. Ví dụ, không còn hoạt động: k = d.keys (); k.sort (). Sử dụng k = sorted (d).
  • Theo đó, các phương thức dict.iterkeys (), dict.iteritems () và dict.itervalues ​​() không còn được hỗ trợ nữa.
  • map () và filter () trả về các trình vòng lặp. Nếu bạn thực sự muốn có một danh sách, cách khắc phục nhanh là danh sách (bản đồ (...)), nhưng cách khắc phục tốt nhất là sử dụng trình tạo danh sách (đặc biệt khi mã gốc sử dụng biểu thức lambda) hoặc viết lại mã để nó không cần một danh sách như vậy. Điều đặc biệt khó là map () gây ra tác dụng phụ của hàm; chuyển đổi chính xác là sử dụng một vòng lặp (tạo một danh sách đơn giản là lãng phí).
  • range () bây giờ hoạt động giống như xrange (), nhưng hoạt động trên các giá trị có kích thước bất kỳ. xrange () không còn tồn tại.
  • zip () trả về một trình lặp.

Toán tử so sánh

Python 3 đã đơn giản hóa các quy tắc cho các toán tử so sánh:

Toán tử so sánh (<, <=, >=,>) đưa ra một ngoại lệ TypeError khi các toán hạng không thể sắp xếp được. Vì vậy, các biểu thức như 1< "", 0 >Không có hoặc len<= len более не разрешены, и, например, None < None поднимает TypeError, а не возвращает False. Следствием является то, что сортировка списка с разными типами данных больше не имеет смысла - все элементы должны быть сравнимы друг с другом. Обратите внимание, что это не относится к операторам == и!=: объекты различных несравнимых типов всегда неравны друг другу.

builtin.sorted () và list.sort () không còn chấp nhận đối số cmp để cung cấp hàm so sánh. Sử dụng đối số chính để thay thế. Các đối số chính và đối số đảo ngược bây giờ là "chỉ từ khóa".

Hàm cmp () không được dùng nữa và phương thức __cmp __ () đặc biệt không được hỗ trợ trong Python 3. Sử dụng __lt __ () để sắp xếp, __eq __ () với __hash __ () để so sánh. (Nếu bạn thực sự muốn chức năng cmp (), bạn có thể sử dụng biểu thức (a> b) - (a< b) в качестве эквивалента для cmp(a, b).)

Số nguyên

  • PEP 0237: dài được đổi tên thành int.
  • PEP 0238: Biểu thức như 1/2 trả về float. Sử dụng 1 // 2 để cắt bớt phần phân số. (Cú pháp này đã tồn tại kể từ Python 2.2)
  • Hằng số sys.maxint đã bị loại bỏ vì không còn giới hạn về giá trị của số nguyên. Tuy nhiên, sys.maxsize có thể được sử dụng như một số lớn hơn bất kỳ danh sách hoặc chỉ mục chuỗi thực tế nào. sys.maxsize tương ứng với kích thước "tự nhiên" của số nguyên và thường có cùng giá trị với sys.maxint trên cùng một nền tảng (giả sử các thông số xây dựng giống nhau).
  • repr () từ một số nguyên dài không bao gồm chữ L tận cùng hơn, vì vậy mã loại bỏ ký tự đó một cách vô điều kiện sẽ loại bỏ chữ số cuối cùng để thay thế. (Sử dụng str () để thay thế.)
  • Chữ bát phân không còn ở dạng 0720; sử dụng 0o720.

Văn bản, Unicode và chuỗi 8 bit

Mọi thứ bạn biết về dữ liệu nhị phân và Unicode đã thay đổi.

Python 3 sử dụng khái niệm văn bản và dữ liệu (nhị phân) thay vì chuỗi Unicode và chuỗi 8 bit. Tất cả văn bản là Unicode; Tuy nhiên, các chuỗi được mã hóa Unicode được biểu diễn dưới dạng dữ liệu nhị phân. Loại được sử dụng để lưu trữ văn bản là, loại được sử dụng để lưu trữ dữ liệu là. Sự khác biệt lớn nhất với python 2.x là bất kỳ nỗ lực nào để kết hợp văn bản và dữ liệu trong Python 3.0 đều tạo ra TypeError, trong khi nếu bạn đang trộn chuỗi Unicode và 8 bit trong Python 2.x, nó sẽ hoạt động nếu chuỗi 8-bit chỉ chứa Các ký tự 7-bit (ASCII), nhưng bạn sẽ nhận được UnicodeDecodeError nếu nó chứa các ký tự không phải ASCII. Hành vi này đã khiến vô số người mặt thương tiếc trong suốt nhiều năm qua.

Do sự thay đổi triết lý này, phần lớn mã sử dụng Unicode, bảng mã hoặc dữ liệu nhị phân có thể sẽ thay đổi. Đây là một thay đổi để tốt hơn vì có rất nhiều lỗi trong python 2.x liên quan đến việc trộn văn bản được mã hóa và giải mã. Để chuẩn bị cho điều này, Python 2.x nên bắt đầu sử dụng Unicode cho tất cả văn bản chưa được mã hóa và str chỉ dành cho dữ liệu nhị phân hoặc mã hóa. Công cụ 2to3 sau đó sẽ thực hiện hầu hết công việc cho bạn.

Bạn không thể sử dụng chữ u "..." cho văn bản Unicode được nữa. Tuy nhiên, bạn phải sử dụng chữ b "..." cho dữ liệu nhị phân.

Vì str và byte không thể trộn lẫn, bạn phải luôn chuyển đổi chúng một cách rõ ràng. Sử dụng str.encode () để chuyển từ str sang byte và byte.decode () để chuyển từ byte sang str. Bạn cũng có thể sử dụng byte (s, encoding = ...) và str (b, encoding = ...), tương ứng.

Giống như str, byte là bất biến. Có một loại có thể thay đổi riêng biệt cho dữ liệu nhị phân, bytearray. Hầu hết tất cả các hàm chấp nhận byte cũng chấp nhận bytearray.

Tất cả các dấu gạch chéo ngược trong các ký tự chuỗi thô được hiểu theo nghĩa đen. Điều này có nghĩa là "\ U" và "\ u" trong chuỗi thô không được xem xét cụ thể. Ví dụ: r "\ u20ac" là một chuỗi 6 ký tự trong Python 3.0, trong khi ở phiên bản 2.6, ur "\ u20ac" là một ký tự euro duy nhất. (Tất nhiên, thay đổi này chỉ ảnh hưởng đến các ký tự chuỗi thô.)

Chuỗi cơ sở kiểu trừu tượng tích hợp đã bị xóa. Sử dụng str thay thế. str và byte không chia sẻ đủ chức năng chung để đảm bảo một lớp cơ sở chung. Công cụ 2to3 (xem bên dưới) thay thế mỗi lần xuất hiện của basestring bằng str.

PEP 3138: repr () cho chuỗi không còn thoát khỏi các ký tự không phải ASCII. Tuy nhiên, nó vẫn thoát khỏi các ký tự điều khiển.

PEP 3120: Mã hóa nguồn mặc định hiện là UTF-8.

PEP 3131: Các ký tự không phải ASCII được phép trong số nhận dạng. (Tuy nhiên, thư viện tiêu chuẩn vẫn là ASCII, ngoại trừ tên tác giả trong nhận xét.)

Các mô-đun StringIO và cStringIO đã bị xóa. Thay vào đó, hãy nhập mô-đun io và sử dụng io.StringIO hoặc io.BytesIO cho văn bản và dữ liệu, tương ứng.

Tổng quan về thay đổi cú pháp

Phần này cung cấp tổng quan nhanh về từng thay đổi cú pháp Python 3.0.

Cú pháp mới

PEP 3107: Chú thích cho đối số hàm và giá trị trả về.

>>> def foo (a: "x", b: 5 + 6, c: list) -> max (2, 9): ... pass >>> foo. __annotations__ ("a": "x", "b": 11, "c": , "return": 9)

PEP 3102: Đối số chỉ từ khóa.

PEP 3104: phi địa phương. Một biến trong phạm vi bên ngoài (nhưng không phải toàn cục).

>>> def bên ngoài (): ... x = 1 ... def bên trong (): ... x = 2 ... in ("bên trong:", x) ... bên trong () ... in ("bên ngoài:", x) ... >>> bên ngoài () bên trong: 2 bên ngoài: 1 >>> bên ngoài (): ... x = 1 ... bên trong (): ... bên ngoài địa phương x ... x = 2 ... print ("inner:", x) ... inner () ... print ("ngoài:", x) ... >>> Ngoài () bên trong: 2 bên ngoài: 2

PEP 3132: Mở rộng đóng gói có thể lặp lại

>>> (a, * rest, b) = range (5) >>> a 0 >>> rest >>> b 4

Trình tạo từ điển: (k: v cho k, v trong nội dung) (giống như dict (nội dung))

Đặt các ký tự (ví dụ: (1, 2)). Lưu ý rằng () là một từ điển trống. Sử dụng set () cho các tập hợp trống. Đặt Trình tạo: (x cho x trong nội dung)

Các ký tự bát phân mới, chẳng hạn như 0o720, thay vì các ký tự cũ (0720).

Các ký tự nhị phân mới chẳng hạn như 0b1010. Chức năng tích hợp mới, bin ().

Cú pháp đã sửa đổi

PEP 3109 và PEP 3134: Cú pháp mới cho câu lệnh raise: raise].

"as" và "with" là các từ dành riêng.

"Đúng" và "Sai" và "Không" là các từ dành riêng.

Đã thay đổi "ngoại trừ exc, var" thành "ngoại trừ exc là var".

PEP 3115: Cú pháp mới cho Metaclasses. Thay vì:

lớp C: __metaclass__ = M ...

Bạn phải dùng:

lớp C (metaclass = M): ...

Biến __metaclass__ không còn được hỗ trợ.

Trình tạo danh sách không còn hỗ trợ dạng cú pháp [... cho var trong item1, item2, ...]. Sử dụng [... cho var in (item1, item2, ...)].

Cú pháp đã xóa

PEP 3113: Đã gỡ bỏ bộ giá trị đóng gói trong các thông số. Bạn không thể viết nữa

def foo (a, (b, c)): ... def foo (a, b_c): b, c = b_c ...

Đã xóa que tính ngược. Sử dụng repr ().

Loại bỏ<>... Sử dụng! =.

thực thi là một hàm. Đã không còn là một từ dành riêng.

từ nhập mô-đun * bị cấm sử dụng bên trong các chức năng.

Chức năng tích hợp sẵn

PEP 3135: Siêu mới (). Bây giờ bạn có thể gọi super () mà không có đối số và (giả sử nó là một phương thức thể hiện được định nghĩa bên trong định nghĩa lớp) thì lớp và thể hiện sẽ được tự động chọn. Với các đối số, hành vi của super () vẫn không thay đổi.

PEP 3111: raw_input () được đổi tên thành input (). Thay vì input () trong Python 2, bạn có thể sử dụng eval (input ()).

Đã thêm hàm next () gọi phương thức __next __ () của đối tượng.

Đã chuyển intern () sang sys.intern ().

Đã xóa: áp dụng (). Sử dụng f (* args) thay vì áp dụng (f, args).

Đã xóa: callable (). Sử dụng hasattr (f, "__call__") thay vì có thể gọi (f). Hàm operator.isCallable () cũng đã bị loại bỏ.

Đã xóa: coerce ().

Đã loại bỏ: executefile (). Sử dụng tệp thực thi (open (fn) .read ()) thay vì tệp thực thi (fn).

Đã xóa: tệp. Sử dụng open ().

Đã chuyển: giảm () thành functools.reduce ()

Đã di chuyển: reload () thành imp.reload ().

Đã xóa: dict.has_key (). Sử dụng toán tử trong.

Bài viết này liệt kê những điểm chính có thể hữu ích khi chuyển sang ngôn ngữ lập trình Python từ một ngôn ngữ lập trình khác hoặc để tự học Python.

Hướng đối tượng

Bạn có thể bỏ qua phần này cho người mới bắt đầu ngay bây giờ và quay lại sau khi đọc phần còn lại của tài liệu!

>>> q = >>> p = >>> len (p) 3 >>> p >>> p 2 >>> p.append ('xtra') >>> p, 4] >>> q

Định nghĩa lớp là một đối tượng, về cơ bản giống như mọi thứ trong một ngôn ngữ.

Nghĩa là, bạn có thể gán định nghĩa lớp cho một biến:

>>> lớp MyClass: ... i = 12345 ... def f (x): ... print dir (x) ... return x ... >>> c = MyClass () >>> i 123 >>> ci 12345 >>> cf > >>> d = MyClass >>> e = MyClass () >>> e<__main__.MyClass instance at 0x000000000239E808>>>> c<__main__.MyClass instance at 0x000000000239E7C8>>>> d >>> d.i 12345 >>> c.i 12345 >>> c.f > >>> e.f > >>> d.f >>> g = d () >>> g.f >

Thụt lề

Thụt lề được sử dụng trong Python để viết các câu lệnh nhóm. Ví dụ: khi bạn xác định một hàm hoặc nội dung vòng lặp, bạn viết tất cả các câu lệnh cần đi vào hàm với cùng một thụt đầu dòng:

Def some_func (z): y = z * 2 # Hàm trả về nội dung y # Đây cũng là một hàm # Và đây không còn là y = 1 print (some_func (y))

Các biến trong Python

Số nguyên và số dấu phẩy động

Bằng cách gán cilo cho một biến không có dấu chấm hoặc sử dụng int (), bạn sẽ nhận được một biến số nguyên. Kết quả của phép chia hai số nguyên cũng sẽ là một số nguyên - phần còn lại của phép chia sẽ bị loại bỏ.

Thêm dấu chấm vào cuối số để tạo số nổi:

Chuỗi trong Python

Thay thế các giá trị thành một chuỗi

Python cho phép bạn tạo một chuỗi bằng cách sử dụng mẫu và thay thế các giá trị biến vào đó.

Có hai tùy chọn để thay thế các giá trị vào một chuỗi: thay thế theo vị trí và sử dụng các tham số được đặt tên.

Sự thay thế vị trí của các giá trị

Output = "Sản phẩm% s trong danh mục% s"% (sản phẩm, danh mục) output = "Bạn có% s $"% usd_count

Trong trường hợp này, giá trị của các biến sẽ được thay thế tuần tự vào chuỗi.

Sử dụng các tham số được đặt tên

Output = "Hôm nay là% (tháng) s% (ngày) s.")% ("Tháng": m, "ngày": d)

Khi sử dụng các tham số đã đặt tên để thay thế thành một chuỗi giá trị, giá trị thay thế theo tên của nó từ từ điển sẽ được chọn.

Phương pháp này phù hợp hơn nếu bạn định dịch dự án của mình sang nhiều ngôn ngữ, vì nó sẽ cho phép người dịch thay đổi thứ tự từ trong mẫu nguồn.

Định dạng và xuất chuỗi

Dấu phẩy ở cuối cho phép bạn chèn một khoảng trắng sau đầu ra của giá trị thay vì một dòng mới:

>>> trong khi b< 10: ... print b, ... b += 1 ... 1 2 3 4 5 6 7 8 9 >>> for x in range (1, 11): ... print str (x) .rjust (2), str (x * x) .rjust (3), ... # Lưu ý dấu phẩy ở cuối dấu dòng trước! ... print str (x * x * x) .rjust (4) ...

Đầu ra được định dạng:

1 1 1 2 4 8 3 9 27 4 16 64 5 25 125 6 36 216 7 49 343 8 64 512 9 81 729 10 100 1000

Ví dụ này minh họa việc sử dụng phương thức rjust () của chuỗi, phương thức này điều chỉnh một chuỗi ở bên phải trong một trường có chiều rộng cho trước, đệm nó sang bên trái bằng khoảng trắng. Phương thức ljust () và center () hoạt động tương tự. Họ không xuất ra bất cứ thứ gì - họ chỉ trả về một dòng mới. Nếu chuỗi ban đầu quá dài, nó không bị cắt bớt, nhưng được trả về không thay đổi: thường tốt hơn là làm rối bố cục cột hơn là in sai giá trị. (Nếu bạn thực sự muốn cắt nó, hãy sử dụng thao tác cắt: 's.ljust (n)'.)

Hàm zfill () được xác định trong mô-đun chuỗi cũng có thể hữu ích,
đệm chuỗi số bằng các số không từ bên trái, xử lý chính xác các dấu cộng và trừ:

>>> nhập chuỗi >>> string.zfill ('12 ', 5)' 00012 '>>> string.zfill (' - 3.14 ', 7)' -003.14 '>>> string.zfill (' 3.14159265359 ', 5) '3,14159265359'

Sử dụng toán tử% trông giống như sau:

>>> import math >>> print ’Giá trị PI xấp xỉ% 5.3f.’% \ ... math.pi Giá trị PI xấp xỉ 3,142.

% để hiển thị thông tin trong 3 cột:

>>> cho x trong khoảng (1,11): ... in '% 2d% 3d% 4d'% (x, x * x, x * x * x) ... 1 1 1 2 4 8 3 9 27 4 16 64 5 25 125 6 36 216 7 49 343 8 64 512 9 81 729 10 100 1000

Phép toán và toán hạng

Phân công

Bạn có thể gán một giá trị cho nhiều biến cùng một lúc

A = b = c = 1 a, b = 0, 1

Luỹ thừa

5 thành lũy thừa của 2 (5 bình phương):

In 5 ** 2

Điều kiện logic

Toán tử in và not in kiểm tra xem giá trị được chỉ định có nằm trong chuỗi không. Toán tử is và not xác định xem hai biến có tham chiếu đến cùng một đối tượng hay không. Tất cả các toán tử này có cùng một mức độ ưu tiên, thấp hơn các toán tử số học.

Biểu thức boolean có thể được xâu chuỗi: ví dụ: 'a< b == c’ проверяет,
là a nhỏ hơn b và b và c bằng nhau.

Biểu thức boolean có thể được nhóm lại bằng cách sử dụng toán tử boolean
và và hoặc, cũng như kết quả, có thể được đảo ngược với toán tử not. Tất cả hợp lý
toán tử có mức độ ưu tiên thấp hơn toán tử so sánh. Trong số các toán tử logic, không có quyền ưu tiên cao nhất và hoặc thấp nhất.

Các hàm tích hợp sẵn trong Python

Tất cả các chức năng được tích hợp trong ngôn ngữ có thể được xem tại đây:

Chu kỳ

Trong khi lặp lại

Vòng lặp while được sử dụng để thực hiện lặp lại các hành động trong khi điều kiện được đáp ứng:

Trong khi expr: suite1

Câu lệnh while được thực hiện theo thứ tự sau:

1. Biểu thức expr được ước lượng và nếu sai, hãy chuyển sang bước 3.
2. Khối mã suite1 được thực thi. Trong trường hợp này, việc thực hiện câu lệnh break trong khối
ngay lập tức làm gián đoạn quá trình thực hiện của vòng lặp (điểm 3 không được thực thi) và việc thực thi
câu lệnh continue làm gián đoạn việc thực thi khối mã, tiếp theo là việc thực thi
chu trình tiếp tục từ bước 1. Sau khi hoàn thành khối suite1, bạn
Chu kỳ tiếp tục từ điểm 1.
3. Khối mã suite2 (nhánh khác) được thực thi. Câu lệnh ngắt và tiếp tục trong
khối này được coi là thuộc về vòng ngoài.

Vòng lặp for

Vòng lặp for trong Python lặp qua các phần tử của một chuỗi tùy ý (ví dụ: một danh sách hoặc một chuỗi) theo thứ tự chúng xuất hiện:

A = ['cat', 'window', 'throw out'] >>> for x in a: ... print x, len (x) ... cat 3 window 4 throw out 9

Các tính năng của vòng lặp for trong Python

Câu lệnh for được sử dụng để lặp qua các phần tử của một chuỗi:

Đối với giá trị theo thứ tự: suite1

Biểu thức trình tự đánh giá một lần và phải dẫn đến một chuỗi (một đối tượng mà trên đó thao tác lấy một phần tử theo chỉ mục được xác định; nếu chỉ mục nằm ngoài phạm vi, một ngoại lệ IndexError phải được ném ra).

Đối với mỗi phần tử của trình tự, theo thứ tự tăng dần của các chỉ số bắt đầu từ 0, một giá trị được gán cho phần tử trình tự và khối mã suite1 được thực thi.

Sau khi trình tự đã hết (được xác định bởi ngoại lệ IndexError), nếu có mệnh đề else, khối suite2 sẽ được thực thi.

Việc thực thi câu lệnh break trong khối suite1 ngay lập tức làm gián đoạn quá trình thực thi vòng lặp (nhánh khác bị bỏ qua). Câu lệnh continue trong suite1 bỏ qua phần còn lại của khối và tiếp tục thực hiện vòng lặp sau khi phần tử tiếp theo của chuỗi đã được gán cho một giá trị hoặc nhánh khác được thực thi nếu không có phần tử tiếp theo trong chuỗi.

Bạn có thể gán cho một biến hoặc cho các biến là một phần của giá trị - điều này sẽ không ảnh hưởng đến phần tử tiếp theo sẽ được gán cho giá trị. Các biến có trong một giá trị không bị xóa sau khi kết thúc vòng lặp và giữ lại các giá trị cuối cùng được gán cho chúng. Tuy nhiên, nếu chuỗi trống, sẽ không có giá trị nào được gán cho giá trị (do đó, sử dụng các biến này mà không cần xác nhận bổ sung, bạn có cơ hội nhận được NameError).

Thay đổi trình tự có thể lặp lại

Hãy cẩn thận khi thay đổi trình tự bạn đang lặp lại. Phần tử hiện tại của dãy được xác định bởi giá trị của bộ đếm bên trong. Phần cuối của chuỗi được phát hiện bởi một ngoại lệ IndexError khi cố gắng lấy phần tử tiếp theo. Do đó, nếu trong block suite1 bạn xóa phần tử hiện tại hoặc một trong các phần tử đã truyền của dãy, phần tử tiếp theo sẽ bị bỏ qua.

Tương tự như vậy, nếu bạn thêm một phần tử mới vào chuỗi trước phần tử hiện tại, phần thân vòng lặp cho phần tử hiện tại sẽ được thực thi lại. Hành vi này có thể dẫn đến các lỗi khó chịu thường có thể tránh được bằng cách lặp lại các phần tử của bản sao của trình tự ban đầu, ví dụ:

For x in a [:]: nếu x< 0: a.remove(x)

Hàm Range () và xrange ()

Nếu bạn cần lặp lại một chuỗi số, thì
hàm range (). Nó tạo ra một danh sách chứa một cấp số cộng:
>>> phạm vi (10)

Hàm xrange hoạt động theo cách tương tự, chỉ thay vì tạo danh sách, nó tạo một đối tượng kiểu xrange - các giá trị của nó có thể được lặp lại trong một vòng lặp, nhưng không thể thay đổi

>>> loại (phạm vi (2)) >>> loại (xrange (2))

Câu lệnh ngắt và tiếp tục, rẽ nhánh khác trong các vòng lặp

Câu lệnh break thoát ra khỏi vòng lặp for hoặc while lồng trong cùng. Câu lệnh continue tiếp tục thực hiện vòng lặp với lần lặp tiếp theo.

Các vòng lặp có thể có một nhánh khác, được thực hiện trên lối ra “bình thường” (hết chuỗi trong vòng lặp for, không thỏa mãn điều kiện trong vòng lặp while), mà không bị ngắt bởi câu lệnh break. Hãy chứng minh công dụng của nó bằng ví dụ về tìm kiếm các số nguyên tố:

>>> for n in xrange (2, 10): ... for x in xrange (2, n): ... if n% x == 0: ... print n, '=', x, ' * ', n / x ... break ... else: ... in n,' - số nguyên tố '... 2 - số nguyên tố 3 - số nguyên tố 4 = 2 * 2 5 - số nguyên tố 6 = 2 * 3 7 - số nguyên tố 8 = 2 * 4 9 = 3 * 3

Chức năng

>>> def fib (n):

Các câu lệnh tạo nên phần thân của hàm được thụt vào, bắt đầu từ dòng tiếp theo. Câu lệnh đầu tiên của một thân hàm có thể là một docstring.

>>> def fib (n): ... ’’ ’Hiển thị số Fibonacci trong số được chỉ định’ ’’ ... a, b = 0, 1 ... while b< n: ... print b, ... a, b = b, a+b

>>> q = range (5) >>> def ch (l): ... l.append ("Mới!") ... >>> q >>> ch (q) >>> q

Câu lệnh return thoát khỏi hàm và trả về một giá trị. Không có đối số, trả về được sử dụng để thoát giữa thủ tục, trong trường hợp này, không trả về.

Các giá trị mặc định được tính toán tại vị trí của định nghĩa hàm trong phạm vi
khả năng hiển thị định nghĩa, do đó

I = 5 def f (arg = i): print arg i = 6 f () sẽ in ra 5.

Lưu ý quan trọng: giá trị mặc định chỉ được tính một lần. Điều này được phản ánh khi đối số mặc định là một đối tượng có thể sửa đổi, chẳng hạn như danh sách hoặc từ điển. Ví dụ, hàm sau đây tích lũy các đối số được truyền vào.

Def f (a, l =): l.append (a) return l print f (1) print f (2) print f (3)

Kết quả thực hiện sẽ như sau:

Tập hợp các đối số tùy ý

Cuối cùng, một tùy chọn ít được sử dụng hơn là xác định một hàm để nó có thể được gọi với một số lượng đối số tùy ý. Trong trường hợp này, các đối số sẽ được chuyển dưới dạng một bộ giá trị. Một số lượng đối số thông thường tùy ý có thể được đặt trước bởi một số lượng biến đối số:

Def fprintf (file, format, * args): file.write (format% args)

Đối số được đặt tên

Hàm có thể được gọi bằng cách sử dụng các đối số được đặt tên (từ khóa
đối số) dưới dạng ‘từ khóa = giá trị’.

Ví dụ Def (đối số chính thức, *, ** từ khóa): print "Đối số bình thường:", in chính thức '-' * 40 đối với đối số: print arg print '-' * 40 đối với kw trong từ khoá.keys (): print kw, ':', từ khóa

Các hàm lambda trong Python

Hàm lambda làm điều tương tự như một hàm thông thường.

Không giống như thông thường, lambda sử dụng cú pháp viết tắt: danh sách đối số được viết không có dấu ngoặc đơn và không có từ khóa trả về. Một thân hàm chỉ có thể chứa một biểu thức. Hàm lambda không có tên, nhưng có thể được gọi thông qua biến mà nó được gán.

>>> g = lambda x: x * 2 >>> g (3)

Đầu vào và đầu ra Python

Đọc và ghi tệp

Hàm tích hợp open () trả về một đối tượng tệp và thường được sử dụng với hai đối số: ‘open (tên tệp, chế độ)’.

>>> f = open ('/ tmp / workfile', 'wb') >>> print f

Đối số đầu tiên là chuỗi chứa tên tệp, đối số thứ hai là chuỗi chứa một số ký tự mô tả chế độ sử dụng tệp. Chế độ có thể là 'r' nếu tệp được mở để chỉ đọc, "w" chỉ để ghi (tệp hiện có sẽ bị ghi đè) và "a" để thêm vào cuối tệp. Ở chế độ 'r +', tệp được mở ngay lập tức để đọc và ghi. Đối số mode là tùy chọn; nếu bị bỏ qua, nó có nghĩa là 'r'.

Trên Windows (và trong một số trường hợp trên Macintosh), tệp được mở ở chế độ văn bản theo mặc định - để mở tệp ở chế độ nhị phân, hãy thêm 'b' vào dòng chế độ. Lưu ý rằng dữ liệu nhị phân như ảnh JPEG và thậm chí cả văn bản UNICODE sẽ bị hỏng khi đọc từ tệp hoặc ghi vào tệp được mở ở chế độ văn bản! Cách tốt nhất để tránh rắc rối cho bản thân là luôn mở tệp ở chế độ nhị phân, ngay cả trên các nền tảng mà chế độ nhị phân được sử dụng theo mặc định (một ngày nào đó bạn có thể muốn chạy chương trình trên nền tảng khác).

Mô-đun dưa chua

Nếu bạn có đối tượng x và đối tượng tệp f đang mở để ghi, cách đơn giản nhất để lưu trữ đối tượng chỉ cần một dòng mã:

Pickle.dump (x, f)

Bạn có thể dễ dàng khôi phục một đối tượng (f là một đối tượng tệp được mở để đọc):

X = pickle.load (f)

Các hàm tích hợp sẵn trong Python

Python đi kèm với nhiều hàm, chẳng hạn như map () và zip (), để làm cho việc tính toán dễ dàng hơn nhiều.

Cấu trúc dữ liệu Python

Danh sách

Danh sách các giá trị được phân tách bằng dấu phẩy nằm trong các ô vuông
dấu ngoặc. Các mục danh sách không cần phải cùng loại.

A = ['spam', 'egg', 100, 1234]

Các mục trong danh sách được đánh số tương tự như chuỗi - mục đầu tiên được đánh số 0.

Phương pháp làm việc với danh sách

nối, bật và chèn

Nối thêm một phần tử mới vào cuối danh sách.

Phương thức chèn cho phép bạn chèn một phần tử vào đầu hoặc một vị trí khác của danh sách - bạn chỉ định chỉ mục của phần tử mà trước đó phần tử mới sẽ được thêm vào:

>>> a.insert (2, -1)

pop () trả về phần tử cuối cùng của danh sách bằng cách xóa nó khỏi danh sách.

chỉ mục và đếm

Chỉ mục sẽ tìm phần tử đầu tiên có giá trị cụ thể ở đâu.

loại bỏ, sắp xếp, đảo ngược

Sử dụng danh sách

chắp thêm và cửa sổ bật cho phép bạn sử dụng danh sách như một ngăn xếp:

>>> stack = >>> stack.append (6) >>> stack.append (7) >>> stack >>> stack.pop () 7 >>> stack

Cũng dễ dàng sử dụng danh sách làm hàng đợi các mục - thêm bằng append và tìm nạp phần đầu tiên trong hàng với pop (0):

>>> queue = ["Eric", "John", "Michael"] >>> queue.append ("Terry") # Terry đã được thêm vào hàng đợi >>> queue.append ("Graham") # Graham đã được thêm vào hàng đợi >>> queue.pop (0) 'Eric' >>> queue.pop (0) 'John' >>> hàng đợi ['Michael', 'Terry', 'Graham']

Lát

Không thể tạo lát cắt từ từ điển và bộ hoặc bộ.
Cách sử dụng phổ biến nhất của các lát trong python là tạo bản sao của một chuỗi hoặc một phần của nó.
Hãy coi một lát cắt như là một phần của một chuỗi. Ví dụ: một số lát từ danh sách:

>>> s = # danh sách đơn giản >>> s [:] # bản sao của danh sách, thường rất hữu ích >>> s # tất cả các phần tử ngoại trừ phần tử đầu tiên >>> s [-3:] # 3 phần tử cuối cùng >>> s # loại bỏ 2 đầu tiên và cuối cùng

Slices có thể có ba tham số:

S [:: 2] # phần tử được ghép nối >>> s # phần tử từ đầu tiên đến thứ tư với bước 2

Tất cả những hành động này có thể được thực hiện với chuỗi, bộ giá trị và danh sách.

>>> "Xin chào Dolly!" "El ol!"

Cách "mở rộng" một chuỗi (tuple, danh sách):

>>> "God saw I was dog" [:: - 1] "god saw I was doG" >>> # bước phủ định có thể là một cú cào nếu bạn không biết chi tiết cụ thể.

Có một số điều bạn có thể làm với các lát cắt mà bạn chỉ có thể làm với danh sách. Thực tế là chúng là những trình tự cơ bản duy nhất có thể thay đổi và thứ tự nào quan trọng. Tiếp theo, chúng ta sẽ nói về các lát thay đổi trình tự.
Bạn có thể xóa:

>>> s = list (range (10)) # điền vào 0..9 >>> del s # xóa các phần tử giữa thứ ba và áp chót với bước 2 >>> s [0, 1, 2, 4, 6 , 8, chín]

Bạn cũng có thể chèn các phần tử:
Trong tùy chọn thay thế:

>>> s = list ("AF") # có một danh sách, chúng tôi đã thay thế các phần tử được chỉ định bằng ['A', 'F'] >>> # yes, trong cấu trúc như vậy, các kích thước cũng phải phù hợp, dễ dàng hơn để hiểu bằng cách thử >>> s [0, 1, "A", 4, "F", 8, 9]

Chà, hoặc một tùy chọn chèn đơn giản hơn:

>>> s = ["4 ở đây"] # thay thế một đoạn tuần tự >>> s [0, 1, "A", "4 ở đây", "F", 8, 9] >>> s = [ "sau số không"] # hoặc chỉ cần chèn >>> s [0, "sau số không", 1, "A", "4 ở đây", "F", 8, 9]

Bạn có thể tạo một lớp mà từ đó bạn có thể tạo các lát cắt.
Ghi đè __getitem__, __setitem__ và __delitem__.
Thoạt nhìn, mọi thứ có vẻ cực kỳ đơn giản, nhưng nếu bạn quan sát kỹ, thì __getitem __ (self, key) - chỉ nhận một tham số, khóa và một lát cắt có thể có 3 số nguyên ... Mọi thứ cực kỳ đơn giản: trong trường hợp khi ai đó cố gắng cắt một lát từ đối tượng của chúng tôi, với giá trị là khóa, hàm sẽ nhận một đối tượng có kiểu lát:

>>> class MySliceble (): def __getitem __ (self, key): if isinstance (key, slice): trả về danh sách (range (key.start, key.stop, key.step)) else: raise Exception ("Đang thử để truy cập theo chỉ mục ") >>> của tôi = MySliceble () >>> của tôi

Tất nhiên, ví dụ này rất tượng trưng, ​​nhưng bạn có thể hiểu nó: một đối tượng của lớp lát cắt có ba thuộc tính: bắt đầu, dừng và bước, tương ứng với các số từ dấu ngoặc của lát cắt. Bạn cần cẩn thận, nếu thiếu số, giá trị sẽ là Không có, ví dụ [::] sẽ là lát (Không có, Không có, Không có) và [: -3] sẽ là lát (Không có, -3, Không có ).
Chúng tôi thực hiện việc thay thế / chèn và xóa các lát cắt bằng cách tương tự.

Tuples

Bộ tuple là một chuỗi các phần tử, được phân tách bằng dấu phẩy và được đặt trong dấu ngoặc đơn. Bản thân bộ tuple không thể được sửa đổi, nhưng nó có thể chứa các phần tử có thể thay đổi.

>>> t = 1, [’foo’, ’bar’] >>> t (1, [’foo’, ’bar’]) >>> t = Traceback (trong cùng cuối cùng): Tệp " ", dòng 1, trong? TypeError: object không hỗ trợ gán mục >>> t.append (’ baz ’) >>> t (1, [’ foo ’,’ bar ’,’ baz ’])

Tạo một bộ giá trị trống

c = ()

Tạo một bộ từ một phần tử

c = (1,)

Dictionaries - từ điển

Tốt nhất nên coi từ điển như một tập hợp các cặp key: value không có thứ tự, yêu cầu các khóa là duy nhất trong cùng một từ điển. Một cặp dấu ngoặc nhọn () tạo ra một từ điển trống. Bằng cách đặt danh sách các cặp khóa: giá trị, cách nhau bằng phần năm, trong dấu ngoặc nhọn, bạn chỉ định nội dung ban đầu của từ điển. Từ điển được viết theo cùng một dạng khi xuất ra.

Để tham chiếu đến một phần tử từ điển, bạn cần chỉ định khóa của nó trong dấu ngoặc vuông.

>>> tel = ("jack": 4098, "sape": 4139) >>> tel ["guideo"] = 4127 >>> tel ("sape": 4139, "guideo": 4127, "jack": 4098) >>> tel ["jack"] 4098 >>> del tel ["sape"] >>> tel ["irv"] = 4127 >>> tel ("guideo": 4127, "irv": 4127, "jack": 4098) >>> tel.keys () ["hướng dẫn", "irv", "jack"] >>> "hướng dẫn" trong tel True

Mô-đun bằng Python

Mô-đun là một tệp chứa các định nghĩa và các hướng dẫn khác bằng ngôn ngữ Python. Tên
tệp được hình thành bằng cách thêm hậu tố (phần mở rộng) ‘.py’ ​​vào tên mô-đun. V
trong một mô-đun, tên của nó có sẵn trong biến toàn cục __name__.

Một mô-đun có thể chứa bất kỳ hướng dẫn nào để khởi tạo nó, không chỉ các định nghĩa hàm. Chúng chỉ được thực thi khi mô-đun được nhập lần đầu tiên.

Nhập các hàm và biến

Biến thể này của câu lệnh nhập cho phép bạn nhập tất cả các tên được xác định trong một mô-đun, ngoại trừ các tên bắt đầu bằng dấu gạch dưới (‘_’):
>>> từ nhập khẩu fibo *

Bắt đầu bằng Python 2.0, bạn có thể thay thế các tên đã nhập bằng cách thực hiện câu lệnh nhập:

Nhập chuỗi dưới dạng _string từ nhập anydbm mở dưới dạng dbopen

Hàm Dir ()

Bạn có thể sử dụng hàm dir () tích hợp để tìm ra các tên được xác định trong một mô-đun. Nó trả về một danh sách các chuỗi đã được sắp xếp:

>>> nhập fibo, sys >>> dir (fibo) ['__name__', 'fib', 'fib2'] >>> dir (sys) ['__name__', 'argv', 'builtin_module_names', 'copyright' , 'exit', 'maxint', 'modules', 'path', 'ps1', 'ps2', 'setprofile', 'settrace', 'stderr', 'stdin', 'stdout', 'version']

Không có đối số, dir () trả về danh sách các tên được xác định trong phạm vi hiện tại:

Danh sách được trả về bởi dir () không chứa tên của các hàm và biến tích hợp sẵn - chúng được xác định trong mô-đun __builtin__ tiêu chuẩn:

Tệp '__init__.py? Trong trường hợp đơn giản nhất, ‘__init__.py’ là một tệp trống, nhưng có thể chứa mã khởi tạo gói và / hoặc đặt biến __all__.

Câu lệnh nhập sử dụng quy ước sau: nếu danh sách có tên __all__ được xác định trong tệp khởi tạo '__init__.py', thì danh sách đó được sử dụng làm danh sách tên mô-đun được nhập khi sử dụng 'từ nhập gói *'. Việc duy trì danh sách này phù hợp với thành phần hiện tại của gói là trách nhiệm của tác giả. Cũng có thể bỏ qua danh sách __all__ nếu tác giả cho rằng nhập * không phù hợp.

Xử lý ngoại lệ

Ví dụ sau cho người dùng thấy lời nhắc cho đến khi một số nguyên được nhập hoặc quá trình thực thi bị gián đoạn (thường là Ctrl-C). Trong trường hợp thứ hai, một ngoại lệ KeyboardInterrupt được đưa ra.

Trong khi 1: try: x = int (raw_input ("Nhập số nguyên:")) break ngoại trừ ValueError: print "Bạn đã sai, vui lòng thử lại ..."

Một câu lệnh try có thể có nhiều hơn một nhánh ngoại trừ, xác định các trình xử lý cho các ngoại lệ khác nhau. Chỉ một trong số chúng sẽ được thực thi (tối đa). Chỉ các ngoại lệ được ném trong nhánh try tương ứng mới được xử lý, không xử lý trong các trình xử lý khác của câu lệnh try. Một số loại ngoại lệ có thể được chỉ định sau từ khóa ngoại trừ dưới dạng một bộ giá trị:

Ngoại trừ (RuntimeError, TypeError, NameError): ... vượt qua

Sau tất cả ngoại trừ các nhánh, câu lệnh try có thể chứa một mệnh đề else, mệnh đề này sẽ được thực thi nếu không có ngoại lệ nào được ném ra trong quá trình thực thi nhánh try.

Các lớp học bằng Python

Các tính năng quan trọng nhất của các lớp: cơ chế kế thừa cho phép một số lớp cơ sở, một lớp dẫn xuất có thể ghi đè lên bất kỳ phương thức nào của các lớp cơ sở, một phương thức có cùng tên lớp cơ sở có thể được gọi từ một phương thức. Các đối tượng có thể chứa bất kỳ lượng dữ liệu nào của riêng chúng.

Cú pháp định nghĩa lớp

Mô hình đơn giản nhất để xác định một lớp như sau:

Class class_name: some_instruction

Tạo đối tượng - Thể hiện của một lớp

Việc khởi tạo lớp sử dụng một bản ghi lời gọi hàm. Chỉ cần nghĩ về một đối tượng lớp như một hàm không tham số trả về một thể hiện đã tạo của lớp.

X = MyClass ()

Ví dụ này tạo một đối tượng "trống".

Một ví dụ về việc tạo một lớp với các thuộc tính và phương thức:

Class MyClass: i = 12345 def f (x): return "Xin chào cả thế giới!"

Trong nhiều trường hợp, cần phải tạo một đối tượng với trạng thái ban đầu cụ thể - đối với điều này, lớp phải chứa một phương thức __init __ () đặc biệt,

lớp MyClass: def __init __ (self): self.data =

Nếu phương thức __init __ () được định nghĩa cho một lớp, thì nó sẽ tự động được gọi khi mỗi thể hiện của lớp này được tạo.

Để linh hoạt hơn, phương thức __init __ () tất nhiên có thể có đối số. Trong trường hợp này, các đối số được sử dụng khi khởi tạo lớp được chuyển đến phương thức __init __ (). Ví dụ:

>>> class Complex: ... def __init __ (self, realpart, imagepart): ... self.r = realpart ... self.i = imagepart ... >>> x = Complex (3.0, -4.5 ) >>> xr, xi (3.0, -4.5)

Phương thức cá thể lớp

Thường phương thức được gọi trực tiếp:

Trong ví dụ của chúng tôi, nó sẽ trả về chuỗi "Xin chào cả thế giới!" Tuy nhiên, không nhất thiết phải gọi phương thức trực tiếp. x.f là một đối tượng và có thể được lưu để sử dụng sau này:

Xf = x.f trong khi 1: in xf ()

Điểm đặc biệt của các phương thức lớp là chúng nhận đối tượng mà chúng thuộc về làm đối số đầu tiên. Trong ví dụ của chúng tôi, việc gọi x.f () hoàn toàn tương đương với MyClass.f (x). Nói chung, việc gọi một phương thức liên kết với một đối tượng có danh sách n đối số hoàn toàn giống như cách gọi phương thức hàm không liên kết tương ứng với danh sách đối số thu được bằng cách thêm đối tượng trước đối số đầu tiên.

Di sản

Định nghĩa của một lớp dẫn xuất có tên ClassB trông như sau:

Lớp ClassB (ClassA): ...

Lớp cơ sở (ClassA) phải được định nghĩa trong phạm vi mà định nghĩa của lớp dẫn xuất ClassB nằm trong đó. Bạn có thể sử dụng một biểu thức thay vì tên lớp cơ sở.

Ví dụ: nếu lớp cơ sở được định nghĩa trong một mô-đun khác:

Lớp ClassB (ModulA.ClassA):

Các lớp dẫn xuất có thể ghi đè các phương thức của các lớp cơ sở. Trên thực tế, một phương thức lớp cơ sở gọi một phương thức khác được định nghĩa cho nó có thể
gọi một phương thức của một lớp dẫn xuất ghi đè phương thức này

>>> lớp ClassA: ... a = "A" ... b = "B" ... def Print_A (self): ... print a ... def Print_B (self): ... print self .b ... def Print_Both (self): ... pring ... def PrintBoth (self): ... print "In A" ... self.Print_A () ... print "In B" .. . self.Print_B () ... >>> a = "aaa" >>> cc = ClassA () >>> cc.Print_A () aaa >>> cc.Print_B () B >>> cc.PrintBoth ( ) In A aaa In BB >>> class ClassB (ClassA): ... def Print_A (self): ... print self.a ... >>> ccc = ClassB () >>> ccc.PrintBoth () In AA In BB

Khi ghi đè một phương thức trong một lớp dẫn xuất, bạn cũng có thể muốn gọi một phương thức lớp cơ sở có cùng tên. Điều này có thể được thực hiện: chỉ cần gọi phương thức bằng cách chỉ định rõ ràng tên lớp:

>>> lớp ClassC (ClassA): ... def Print_A (self): ... print "In bằng phương thức cũ từ ClassA" ... ClassA.Print_A (self) ... >>> c = ClassC () >>> c.PrintBoth () In A Print sử dụng phương pháp cũ từ ClassA aaa Printing BB

Đa kế thừa trong Python

Python có hỗ trợ đa kế thừa. Để làm cho lớp mới của bạn kế thừa các thuộc tính và phương thức của một số lớp khác, chỉ cần liệt kê chúng được phân tách bằng dấu phẩy trong định nghĩa của lớp mới:

>>> lớp ClassD (ClassB, ClassA): ... "Kiểm tra tính kế thừa" ... ... >>> d = ClassD () >>> d.PrintBoth () In A A In B B

Một sắc thái quan trọng trong đa kế thừa là lược đồ tìm kiếm đối tượng (phân giải tên) - đầu tiên, tìm kiếm theo chiều sâu, sau đó từ trái sang phải.

Điều này có nghĩa là nếu tên của một phương thức hoặc thuộc tính nằm trong cả hai lớp mà bạn kế thừa, thì tên có mặt trong lớp đầu tiên hoặc tổ tiên của nó sẽ được sử dụng.

Thuộc tính riêng tư

>>> class clA: ... __privateA = "aaa" ... def prn (s): ... print s .__ privateA ... >>> class clB (clA): ... __privateA = "bbb "... >>> A = clB () >>> A.prn () aaa >>> A .__ privateA Traceback (lần gọi gần đây nhất): Tệp" ", dòng 1, trong AttributeError: clB instance không có thuộc tính "__privateA" >>> dir (A) ["__doc__", "__module__", "_clA__privateA", "_clB__privateA", "prn"] >>> A._clB__privateA "bbb" >>>

Ví dụ thực tế

Làm cách nào để loại bỏ tất cả các ký tự ngoại trừ số khỏi một chuỗi trong Python?

>>> nhập lại >>> re.sub ("[^ 0-9]", "", "sdkjh987978asd098as0980a98sd") "987978098098098"

Một điều thú vị mà tôi đã thấy hôm nay là khi tôi gán một hàm cho một thành viên trong lớp, nó sẽ trở thành một phương thức không liên kết. Nhu la:

Kiểm tra lớp (đối tượng): @classmethod def initialize_class (cls): def print_string (self, str): print (str) # Ở đây nếu tôi thực hiện print (print_string), tôi thấy một hàm cls.print_proc = print_string # Ở đây nếu tôi làm print (cls.print_proc), tôi thấy một phương thức không liên kết; vì vậy nếu tôi # nhận được một đối tượng Kiểm tra o, tôi có thể gọi o.print_proc ("Xin chào")

2018-12-04T00: 00Z

khá khó hiểu

Chà, đây là một chủ đề khá phức tạp và liên quan đến bộ mô tả.

Hãy bắt đầu với một hàm. Mọi thứ đều rõ ràng ở đây - bạn chỉ cần gọi nó, tất cả các đối số được cung cấp sẽ được chuyển khi nó được thực thi:

>>> f = A .__ dict __ ["f1"] >>> f (1) 1

Một TypeError thông thường được đưa ra trong trường hợp có sự cố với số lượng tham số:

>>> ", dòng 1, trong TypeError: f1 () nhận đúng 1 đối số (0 cho trước)

Bây giờ các phương pháp. Các phương pháp là các chức năng với một chút gia vị. Có bộ mô tả ở đây. Như được mô tả trong mô hình dữ liệu, A.f1 và A (). F1 dịch sang A .__ dict __ ["f1"] .__ get __ (None, A) và nhập (a) .__ dict __ ["f1" ] .__ lấy __ (a, gõ (a)) tương ứng. Và kết quả của __get__ này khác với hàm f1 thô. Các đối tượng này bao bọc xung quanh f1 ban đầu và chứa một số logic bổ sung.

Trong trường hợp của phương thức không liên kết, logic này liên quan đến việc kiểm tra xem đối số đầu tiên có phải là một thể hiện của A hay không:

>>> f = A.f1 >>> f () Traceback (lần gọi gần đây nhất): Tệp " ", dòng 1, trong TypeError: phương thức unbound f1 () phải được gọi với A instance làm đối số đầu tiên (không có gì thay thế) >>> f (1) Traceback (lần gọi gần đây nhất): File " ", dòng 1, trong TypeError: phương thức unbound f1 () phải được gọi với A instance làm đối số đầu tiên (get int instance thay thế)

Nếu kiểm tra này thành công, nó sẽ chạy f1 ban đầu với trường hợp này là đối số đầu tiên:

>>> f (A ())<__main__.A object at 0x800f238d0>

Lưu ý rằng thuộc tính im_self là Không có:

>>> f.im_self là Không Đúng

Trong trường hợp của phương thức bị ràng buộc, logic này ngay lập tức cung cấp f1 ban đầu với thể hiện của A đã được tạo (thể hiện này thực sự được lưu trữ trong im_self):

>>> f = A (). f1 >>> f.im_self<__main__.A object at 0x800f23950>>>> f ()<__main__.A object at 0x800f23950>

Do đó, ràng buộc có nghĩa là hàm cơ bản được liên kết với một số trường hợp. unbound nghĩa là nó vẫn bị ràng buộc, nhưng chỉ với class.

2018-12-11T00: 00Z

Diễn giải của tôi như sau.

Các đoạn của lớp Chức năng:

Hàm Class (đối tượng):. ... ... def __get __ (self, obj, objtype = None): "Mô phỏng func_descr_get () trong Objects / funcobject.c" nếu obj là Không: trả về các loại tự trả về.MethodType (self, obj)

Hàm Class (đối tượng):. ... ... def __get __ (self, obj, objtype = None): "Mô phỏng func_descr_get () trong các loại trả về Objects / funcobject.c ".MethodType (self, obj, objtype)

  1. Nếu một hàm được gọi mà không có lớp hoặc thể hiện, nó là một hàm đơn giản.
  2. Nếu một hàm được gọi từ một lớp hoặc cá thể, __get__ của nó được gọi để truy xuất hàm được bao bọc:
    Một. Bx giống với B .__ dict __ ["x"] .__ get __ (Không, B). Trong Python 3, hàm này trả về một hàm bình thường. Trong Python 2, hàm này trả về một hàm không liên kết.

    NS. bx giống với kiểu (b) .__ dict __ ["x"] .__ get __ (b, type (b). Điều này sẽ trả về một phương thức liên kết trong cả Python 2 và Python 3, có nghĩa là tự sẽ ngầm định được truyền làm đối số đầu tiên ...