Câu hỏi Các tính năng ẩn của Python [đã đóng]


Các tính năng ít được biết đến nhưng hữu ích hơn của ngôn ngữ lập trình Python là gì?

  • Cố gắng giới hạn câu trả lời cho lõi Python.
  • Một tính năng cho mỗi câu trả lời.
  • Đưa ra một ví dụ và mô tả ngắn về tính năng, không chỉ là một liên kết đến tài liệu.
  • Gắn nhãn đối tượng địa lý bằng tiêu đề làm dòng đầu tiên.

Liên kết nhanh đến câu trả lời:


1420


gốc




Các câu trả lời:


Chaining toán tử so sánh:

>>> x = 5
>>> 1 < x < 10
True
>>> 10 < x < 20 
False
>>> x < 10 < x*10 < 100
True
>>> 10 > x <= 9
True
>>> 5 == x > 4
True

Trong trường hợp bạn đang nghĩ nó đang làm 1 < x, xuất hiện dưới dạng Truevà sau đó so sánh True < 10, cũng là True, sau đó không, đó thực sự không phải là những gì xảy ra (xem ví dụ cuối cùng.) Nó thực sự dịch sang 1 < x and x < 10x < 10 and 10 < x * 10 and x*10 < 100, nhưng với ít đánh máy hơn và mỗi thuật ngữ chỉ được đánh giá một lần.


741



Điều đó rất hữu ích. Nó phải là tiêu chuẩn cho tất cả các ngôn ngữ. Đáng buồn thay, nó không phải là. - stalepretzel
bạn nên thêm một số ví dụ trả về false. chẳng hạn như >>> 10 <x <20 False - ShoeLace
Điều này cũng áp dụng cho các toán tử so sánh khác, đó là lý do tại sao mọi người đôi khi ngạc nhiên tại sao mã như (5 trong [5] là True) là False (nhưng nó không rõ ràng để kiểm tra một cách rõ ràng với các toán tử như thế để bắt đầu). - Miles
Tốt nhưng xem ra cho prcedence bằng nhau, như 'in' và '='. 'A trong B == C trong D' có nghĩa là '(A trong B) và (B == C) và (C trong D)' có thể là bất ngờ. - Charles Merriam
Azafe: So sánh của Lisp tự nhiên hoạt động theo cách này. Nó không phải là một trường hợp đặc biệt bởi vì không có cách nào khác (hợp lý) để giải thích (< 1 x 10). Bạn thậm chí có thể áp dụng chúng vào các đối số đơn lẻ, như (= 10): cs.cmu.edu/Groups/AI/html/hyperspec/HyperSpec/Body/… - Ken


Lấy cây phân tích cú pháp regex python để gỡ lỗi regex của bạn.

Biểu thức chính quy là một tính năng tuyệt vời của python, nhưng gỡ lỗi chúng có thể là một nỗi đau và tất cả đều quá dễ dàng để có được một regex sai.

May mắn thay, python có thể in cây phân tích cú pháp regex, bằng cách chuyển cờ không có giấy tờ, thử nghiệm, ẩn re.DEBUG (thực sự, 128) đến re.compile.

>>> re.compile("^\[font(?:=(?P<size>[-+][0-9]{1,2}))?\](.*?)[/font]",
    re.DEBUG)
at at_beginning
literal 91
literal 102
literal 111
literal 110
literal 116
max_repeat 0 1
  subpattern None
    literal 61
    subpattern 1
      in
        literal 45
        literal 43
      max_repeat 1 2
        in
          range (48, 57)
literal 93
subpattern 2
  min_repeat 0 65535
    any None
in
  literal 47
  literal 102
  literal 111
  literal 110
  literal 116

Khi bạn hiểu cú pháp, bạn có thể phát hiện ra lỗi của mình. Ở đó chúng ta có thể thấy rằng tôi đã quên thoát khỏi [] trong [/font].

Tất nhiên bạn có thể kết hợp nó với bất kỳ cờ nào bạn muốn, như regexes đã nhận xét:

>>> re.compile("""
 ^              # start of a line
 \[font         # the font tag
 (?:=(?P<size>  # optional [font=+size]
 [-+][0-9]{1,2} # size specification
 ))?
 \]             # end of tag
 (.*?)          # text between the tags
 \[/font\]      # end of the tag
 """, re.DEBUG|re.VERBOSE|re.DOTALL)

512



Ngoại trừ phân tích cú pháp HTML bằng cách sử dụng biểu thức chính quy là chậm và đau đớn. Ngay cả mô-đun phân tích cú pháp 'html' được tích hợp sẵn cũng không sử dụng các regex để hoàn thành công việc. Và nếu mô-đun html không làm hài lòng bạn, có rất nhiều mô-đun phân tích cú pháp XML / HTML thực hiện công việc mà không cần phải tái tạo lại bánh xe. - BatchyX
Một liên kết đến tài liệu về cú pháp đầu ra sẽ là tuyệt vời. - Personman
Điều này phải là một phần chính thức của Python, không phải là thử nghiệm ... RegEx luôn khó khăn và có thể theo dõi những gì đang xảy ra thực sự hữu ích. - Cahit


liệt kê

Gói một iterable với liệt kê và nó sẽ mang lại cho mục cùng với chỉ mục của nó.

Ví dụ:


>>> a = ['a', 'b', 'c', 'd', 'e']
>>> for index, item in enumerate(a): print index, item
...
0 a
1 b
2 c
3 d
4 e
>>>

Tham khảo:


460



Tôi ngạc nhiên điều này không được bảo hiểm thường xuyên trong hướng dẫn nói về danh sách python. - Draemon
Và tất cả thời gian này tôi đã được mã hóa theo cách này: cho tôi trong phạm vi (len (a)): ... và sau đó sử dụng một [i] để có được mục hiện tại. - Fernando Martin
@Berry Tsakala: Theo hiểu biết của tôi, nó đã không được chấp nhận. - JAB
Holy crap này thật tuyệt vời. cho i in xrange (len (a)): luôn là thành ngữ python được yêu thích nhất của tôi. - Personman
liệt kê có thể bắt đầu từ chỉ số tùy ý, không cần thiết 0. Ví dụ: 'cho i, mục trong liệt kê (danh sách, start = 1): print i, item 'sẽ bắt đầu đếm từ 1, không phải 0. - dmitry_romanov


Tạo các đối tượng máy phát điện

Nếu bạn viết

x=(n for n in foo if bar(n))

bạn có thể lấy máy phát và gán nó cho x. Bây giờ nó có nghĩa là bạn có thể làm

for n in x:

Ưu điểm của điều này là bạn không cần bộ nhớ trung gian, mà bạn sẽ cần nếu bạn đã làm

x = [n for n in foo if bar(n)]

Trong một số trường hợp, điều này có thể dẫn đến tăng tốc đáng kể.

Bạn có thể nối thêm nhiều câu lệnh if vào cuối trình tạo, về cơ bản nhân bản lồng nhau cho các vòng lặp:

>>> n = ((a,b) for a in range(0,2) for b in range(4,6))
>>> for i in n:
...   print i 

(0, 4)
(0, 5)
(1, 4)
(1, 5)

419



Bạn cũng có thể sử dụng một danh sách lồng nhau hiểu cho rằng, có? - shapr
Lưu ý đặc biệt là tiết kiệm chi phí bộ nhớ. Giá trị được tính theo yêu cầu, do đó bạn không bao giờ có toàn bộ kết quả của việc hiểu danh sách trong bộ nhớ. Điều này đặc biệt mong muốn nếu sau này bạn chỉ lặp lại một phần của việc hiểu danh sách. - saffsd
Đây không phải là đặc biệt "ẩn" imo, nhưng cũng đáng chú ý là một thực tế là bạn không thể tua lại một đối tượng máy phát điện, trong khi bạn có thể nhắc lại trên một danh sách bất kỳ số lần. - susmits
Tính năng "không tua lại" của máy phát có thể gây ra một số nhầm lẫn. Cụ thể, nếu bạn in nội dung của trình tạo để gỡ lỗi, hãy sử dụng nó sau để xử lý dữ liệu, nó không hoạt động. Dữ liệu được tạo ra, được tiêu thụ bởi print (), sau đó không có sẵn cho việc xử lý thông thường. Điều này không áp dụng cho việc hiểu danh sách, vì chúng được lưu trữ hoàn toàn trong bộ nhớ. - johntellsall
Câu trả lời tương tự (dup?): stackoverflow.com/questions/101268/hidden-features-of-python/… Tuy nhiên, lưu ý rằng câu trả lời tôi liên kết ở đây đề cập đến một bài thuyết trình thực sự TỐT về sức mạnh của máy phát điện. Bạn thực sự nên kiểm tra xem nó ra. - Denilson Sá Maia


iter () có thể lấy một đối số có thể gọi

Ví dụ:

def seek_next_line(f):
    for c in iter(lambda: f.read(1),'\n'):
        pass

Các iter(callable, until_value) chức năng nhiều lần gọi callable và mang lại kết quả cho đến until_value Được trả lại.


353



@Cristian Điều này có rõ ràng hơn không? - badp
Là một newbie để python, bạn có thể vui lòng giải thích lý do tại sao lambda từ khóa là cần thiết ở đây? - SiegeX
@SiegeX không có lambda, f.read (1) sẽ được đánh giá (trả về một chuỗi) trước khi được chuyển tới hàm lặp. Thay vào đó, lambda tạo ra một hàm ẩn danh và chuyển nó đến lần lặp. - jmilloy


Hãy cẩn thận với các đối số mặc định có thể thay đổi

>>> def foo(x=[]):
...     x.append(1)
...     print x
... 
>>> foo()
[1]
>>> foo()
[1, 1]
>>> foo()
[1, 1, 1]

Thay vào đó, bạn nên sử dụng giá trị sentinel biểu thị "không được cung cấp" và thay thế bằng biến thể bạn muốn làm mặc định:

>>> def foo(x=None):
...     if x is None:
...         x = []
...     x.append(1)
...     print x
>>> foo()
[1]
>>> foo()
[1]

339



Đó chắc chắn là một trong những tính năng ẩn khó chịu hơn. Tôi đã gặp phải nó theo thời gian. - Torsten Marek
Tôi thấy điều này dễ hiểu hơn nhiều khi tôi biết rằng các đối số mặc định sống trong một bộ dữ liệu là thuộc tính của hàm, ví dụ: foo.func_defaults. Mà, là một tuple, là bất biến. - Robert Rossney
@grayger: Khi câu lệnh def được thực thi, các đối số của nó được đánh giá bởi trình thông dịch. Điều này tạo ra (hoặc rebinds) một tên cho một đối tượng mã (bộ chức năng). Tuy nhiên, các đối số mặc định được khởi tạo như các đối tượng tại thời điểm định nghĩa. Điều này đúng với bất kỳ thời gian nào của đối tượng mặc định, nhưng chỉ có ý nghĩa (hiển thị ngữ nghĩa có thể nhìn thấy) khi đối tượng có thể thay đổi. Không có cách nào để ràng buộc lại tên đối số mặc định đó trong phần đóng của hàm mặc dù nó rõ ràng có thể bị over-ridden cho bất kỳ cuộc gọi nào hoặc toàn bộ hàm có thể được xác định lại). - Jim Dennis
@ Robert dĩ nhiên các đối số tuple có thể là bất biến, nhưng các đối tượng nó trỏ đến không nhất thiết phải bất biến. - poolie
Một bản hack nhanh để khởi tạo ngắn hơn một chút: x = x hoặc []. Bạn có thể sử dụng nó thay vì dòng 2 nếu câu lệnh. - dave mankoff


Gửi các giá trị vào các hàm của trình tạo. Ví dụ như có chức năng này:

def mygen():
    """Yield 5 until something else is passed back via send()"""
    a = 5
    while True:
        f = (yield a) #yield a and possibly get f in return
        if f is not None: 
            a = f  #store the new value

Bạn có thể:

>>> g = mygen()
>>> g.next()
5
>>> g.next()
5
>>> g.send(7)  #we send this back to the generator
7
>>> g.next() #now it will yield 7 until we send something else
7

317



Trong các ngôn ngữ khác, tôi tin rằng thiết bị huyền diệu này được gọi là "biến". - finnw
coroutines nên được coroutines và genenerator nên được bản thân quá, mà không cần trộn. Liên kết và trò chuyện và ví dụ tuyệt vời về điều này ở đây: dabeaz.com/coroutines - u0b34a0f6ae
Đây là một tính năng không ẩn - Justin
@finnw: ví dụ thực hiện một cái gì đó tương tự như một biến. Tuy nhiên, tính năng này có thể được sử dụng theo nhiều cách khác ... không giống như một biến. Nó cũng nên được rõ ràng rằng ngữ nghĩa tương tự có thể được thực hiện bằng cách sử dụng các đối tượng (một lớp thực hiện Python của gọi điện phương pháp, đặc biệt). - Jim Dennis
Đây là một ví dụ quá nhỏ đối với những người chưa bao giờ thấy (và có lẽ sẽ không hiểu) đồng-thói quen. Ví dụ thực hiện trung bình đang chạy mà không có nguy cơ tràn biến sum là một ví dụ tốt. - Prashant Kumar


Nếu bạn không thích sử dụng khoảng trống để biểu thị phạm vi, bạn có thể sử dụng kiểu C {} bằng cách phát hành:

from __future__ import braces

314



Đó là điều ác. :) - Jason Baker
>>> từ __future__ niềng răng nhập khẩu Tệp "<stdin>", dòng 1 Cú phápError: không phải là cơ hội: P - Benjamin W. Smith
đó là báng bổ! - Berk D. Demir
Tôi nghĩ rằng chúng tôi có thể có một sai lầm cú pháp ở đây, không phải là "từ __quá khứ__ niềng răng nhập khẩu "? - Bill K
từ __cruft__ nhập khẩu niềng răng - Phillip B Oldham