Các tính năng ẩn của Python [đã đóng]


1419

Các tính năng ít được biết đến nhưng hữu ích 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.
  • Dán nhãn cho tính năng sử dụng tiêu đề làm dòng đầu tiên.

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

Câu trả lời:


740

Toán tử so sánh chuỗi:

>>> 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ĩ rằng nó đang hoạt động 1 < x, xuất hiện True, và sau đó so sánh True < 10, thì cũng Truekhông, đó thực sự không phải là điều xảy ra (xem ví dụ cuối cùng.) Nó thực sự được dịch sang 1 < x and x < 10, và x < 10 and 10 < x * 10 and x*10 < 100với việc gõ ít hơn và mỗi lần gõ hạn chỉ được đánh giá một lần.


121
Đ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

8
bạn nên thêm một số ví dụ trả về false aswell. chẳng hạn như >>> 10 <x <20 Sai
ShoeLace

19
Đ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à Đúng) là sai (nhưng không rõ ràng để kiểm tra rõ ràng đối với các booleans như thế bắt đầu).
Miles

19
Tốt nhưng coi chừng sự bình đẳng như nhau, như 'trong' và '='. 'A in B == C in D' có nghĩa là '(A in B) và (B == C) và (C in D)' có thể gây bất ngờ.
Charles Merriam

15
Azafe: So sánh của Lisp tự nhiên hoạt động theo cách này. Đây không phải là trường hợp đặc biệt vì không có cách giải thích (hợp lý) nào khác (< 1 x 10). Bạn thậm chí có thể áp dụng chúng cho các đối số duy nhất, như (= 10): cs.cmu.edu/group/AI/html/hyperspec/HyperSpec/Body/iêu
Ken

512

Lấy cây parex regex python để gỡ lỗi regex của bạn.

Biểu thức thông thường là một tính năng tuyệt vời của python, nhưng việc gỡ lỗi chúng có thể là một nỗi đau và quá dễ để có một biểu thức chính xác.

May mắn thay, python có thể in cây phân tích regex, bằng cách chuyển cờ không có giấy tờ, thử nghiệm, ẩn re.DEBUG(thực tế, 128) cho 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ư biểu thức chính 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)

3
Ngoại trừ phân tích cú pháp HTML bằng cách sử dụng biểu thức thông thường là chậm và đau đớn. Ngay cả mô-đun trình phân tích cú pháp 'html' tích hợp cũng không sử dụng biểu thức chính quy để 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 trình phân tích cú pháp XML / HTML thực hiện công việc mà không phải phát minh 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.
Nhân viên

1
Đây phải là một phần chính thức của Python, không phải 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

460

liệt kê

Bọc một vòng lặp với liệt kê và nó sẽ mang lại vật phẩm cùng với chỉ số 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
>>>

Người giới thiệu:


56
Tôi ngạc nhiên khi điều này không được đề cập thường xuyên trong các bài hướng dẫn nói về danh sách trăn.
Draemon

45
Và tất cả thời gian này tôi đã mã hóa theo cách này: cho i trong phạm vi (len (a)): ... và sau đó sử dụng [i] để lấy mục hiện tại.
Fernando Martin

4
@ BlackBerry Tsakala: Theo hiểu biết của tôi, nó đã không bị phản đối.
JAB

23
Holy crap này là tuyệt vời. for i in xrange (len (a)): luôn là thành ngữ python yêu thích nhất của tôi.
Nhân viên

15
liệt kê có thể bắt đầu từ chỉ số tùy ý, không cần thiết 0. Ví dụ: 'for i, item in
enum Cả

419

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 ra trình tạo 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 việc này là bạn không cần lưu trữ trung gian, 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 sao chép 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)

Bạn cũng có thể sử dụng một sự hiểu biết danh sách lồng nhau cho điều đó, vâng?
shapr

54
Đặc biệt lưu ý là tiết kiệm chi phí bộ nhớ. Các 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

19
Đây không phải là imo "ẩn" đặc biệt, nhưng cũng đáng chú ý là thực tế là bạn không thể tua lại một đối tượng trình tạo, trong khi bạn có thể nhắc lại một danh sách bất kỳ số lần nào.
ảnh hưởng đến

13
Tính năng "không tua lại" của máy phát điện 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, sau đó sử dụng nó để xử lý dữ liệu, nó không hoạt động. Dữ liệu được tạo ra, được sử dụng bởi print (), sau đó không có sẵn để 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 hoàn toàn được lưu trữ trong bộ nhớ.
johntellsall

4
Tương tự (? Dup) câu trả lời: stackoverflow.com/questions/101268/hidden-features-of-python/... Lưu ý, tuy nhiên, 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 nó.
Denilson Sá Maia

353

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

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 liên tục gọi callablevà mang lại kết quả của nó cho đến khi until_valueđược trả về.


Là một người mới chơi python, bạn có thể giải thích tại sao lambdatừ khóa là cần thiết ở đây không?
Cuộc bao vây

@SiegeX không có lambda, f.read (1) sẽ được đánh giá (trả về một chuỗi) trước khi được chuyển đến hàm iter. Thay vào đó, lambda tạo ra một hàm ẩn danh và chuyển nó cho iter.
jmilloy

339

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 giá trị có thể thay đổi mà bạn muốn như mặc định:

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

39
Đó chắc chắn là một trong những tính năng ẩn khó chịu hơn. Thỉnh thoảng tôi cũng gặp phải nó.
Torsten Marek

77
Tôi thấy điều này dễ hiểu hơn rất nhiều khi tôi biết rằng các đối số mặc định sống trong một tuple đó là một 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

2
@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ộ hàm). Tuy nhiên, các đối số mặc định được khởi tạo dưới dạng đối tượng tại thời điểm định nghĩa. Điều này đúng với bất kỳ thời điểm nào của đối tượng mặc định, nhưng chỉ có ý nghĩa (phơi bày ngữ nghĩa hiển thị) 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 bao đóng của hàm mặc dù rõ ràng nó có thể bị quá tải 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

3
@Robert tất nhiên các đối số tuple có thể là bất biến, nhưng các đối tượng mà nó chỉ ra không nhất thiết là bất biến.
poolie

16
Một cách nhanh chóng để làm cho việc khởi tạo của bạn ngắn hơn một chút: x = x hoặc []. Bạn có thể sử dụng thay cho câu lệnh if 2.
dave mankoff

317

Gửi các giá trị vào các hàm tạo . Ví dụ: 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

Đã đồng ý. Chúng ta hãy coi đây là một ví dụ khó chịu về một tính năng ẩn của Python :)
Rafał Dowgird

89
Trong các ngôn ngữ khác, tôi tin rằng thiết bị ma thuật này được gọi là "biến".
Finnw

5
coroutines nên là coroutines và genenerator cũng nên là chính họ, không trộn lẫn. Liên kết tuyệt vời và nói chuyện và các ví dụ về điều này ở đây: dabeaz.com/coroutines
u0b34a0f6ae

31
@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. Rõ ràng là 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 (cụ thể là một lớp ngụ ý phương thức gọi của Python ).
Jim Dennis

4
Đây là một ví dụ quá tầm thường đối với những người chưa từng thấy (và có lẽ sẽ không hiểu) các thói quen chung. Ví dụ thực hiện trung bình đang chạy mà không có rủi ro tràn tổng biến là một ví dụ tốt.
Prashant Kumar

313

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

122
Điều đó thật xấu xa. :)
Jason Baker

37
>>> từ __future__ nhập tệp niềng răng "<stdin>", dòng 1 Cú pháp: không có cơ hội: P
Benjamin W. Smith

40
đó là sự báng bổ!
Berk D. Demir

335
Tôi nghĩ rằng chúng ta có thể có một lỗi cú pháp ở đây, không nên là "từ __past__ nhập khẩu niềng răng"?
Bill K

47
từ __cruft__ niềng răng nhập khẩu
Phillip B Oldham

305

Đối số bước trong toán tử lát. Ví dụ:

a = [1,2,3,4,5]
>>> a[::2]  # iterate over the whole list in 2-increments
[1,3,5]

Trường hợp đặc biệt x[::-1]là một thành ngữ hữu ích cho 'x đảo ngược'.

>>> a[::-1]
[5,4,3,2,1]

31
Rõ ràng hơn nhiều, theo ý kiến ​​của tôi, là hàm đảo ngược (). >>> danh sách (đảo ngược (phạm vi (4))) [3, 2, 1, 0]
Christian Oudard

3
Vậy làm thế nào để viết "chuỗi ia này" [:: - 1] theo cách tốt hơn? đảo ngược dường như không giúp được gì
Berry Tsakala

24
Vấn đề với Reverseed () là nó trả về một trình vòng lặp, vì vậy nếu bạn muốn duy trì kiểu của chuỗi đảo ngược (tuple, chuỗi, list, unicode, kiểu người dùng ...), bạn cần thêm một bước để chuyển đổi lại .
Rafał Dowgird

6
def Reverse_ chuỗi (chuỗi): chuỗi trả về [:: - 1]
pi.

4
@pi Tôi nghĩ rằng nếu một người biết đủ để xác định Reverse_ chuỗi như bạn có thì người ta có thể để lại [:: - 1] trong mã của bạn và thoải mái với ý nghĩa của nó và cảm giác nó phù hợp.
vật lý

289

Trang trí

Trình trang trí cho phép bọc một chức năng hoặc phương thức trong một chức năng khác có thể thêm chức năng, sửa đổi đối số hoặc kết quả, v.v. Bạn viết trang trí một dòng trên định nghĩa hàm, bắt đầu bằng dấu "tại" (@).

Ví dụ hiển thị một trình print_argstrang trí in các đối số của hàm được trang trí trước khi gọi nó:

>>> def print_args(function):
>>>     def wrapper(*args, **kwargs):
>>>         print 'Arguments:', args, kwargs
>>>         return function(*args, **kwargs)
>>>     return wrapper

>>> @print_args
>>> def write(text):
>>>     print text

>>> write('foo')
Arguments: ('foo',) {}
foo

54
Khi xác định trang trí, tôi khuyên bạn nên trang trí trang trí bằng @decorator. Nó tạo ra một trang trí bảo tồn một chữ ký chức năng khi thực hiện nội tâm trên nó. Thêm thông tin ở đây: phyast.pitt.edu/~michele/python/documentation.html
sirwart

45
Làm thế nào đây là một tính năng ẩn?
Vetle

50
Chà, nó không có trong hầu hết các hướng dẫn Python đơn giản và tôi tình cờ thấy nó rất lâu sau khi tôi bắt đầu sử dụng Python. Đó là những gì tôi sẽ gọi là một tính năng ẩn, gần giống như các bài viết hàng đầu khác ở đây.
DzinX

16
vetler, các câu hỏi yêu cầu "các tính năng ít được biết đến nhưng hữu ích của ngôn ngữ lập trình Python." Làm thế nào để bạn đo lường 'các tính năng ít được biết đến nhưng hữu ích'? Tôi có nghĩa là làm thế nào bất kỳ trong số những phản ứng này ẩn các tính năng?
Johnd

4
@vetler Hầu hết mọi thứ ở đây hầu như không "ẩn".
Humphrey Bogart

288

Cú pháp for ... other (xem http://docs.python.org/ref/for.html )

for i in foo:
    if i == 0:
        break
else:
    print("i was never 0")

Khối "khác" sẽ được thực thi bình thường ở cuối vòng lặp for, trừ khi ngắt được gọi.

Các mã trên có thể được mô phỏng như sau:

found = False
for i in foo:
    if i == 0:
        found = True
        break
if not found: 
    print("i was never 0")

218
Tôi nghĩ cú pháp for / other là vụng về. Nó "cảm thấy" như thể mệnh đề khác sẽ được thực thi nếu phần thân của vòng lặp không bao giờ được thực thi.
codeape

14
Ah. Chưa bao giờ thấy cái đó! Nhưng tôi phải nói rằng đó là một chút sai lầm. Ai có thể mong đợi khối khác chỉ thực hiện nếu phá vỡ không bao giờ thực hiện? Tôi đồng ý với codeape: Có vẻ như những thứ khác được đưa vào cho foos trống.
Daren Thomas

52
có vẻ như từ khóa cuối cùng, không phải là khác
Jiaaro

21
Ngoại trừ cuối cùng đã được sử dụng theo cách mà bộ phần mềm đó luôn được thực thi.

7
Chắc chắn không nên là 'người khác'. Có thể 'sau đó' hoặc một cái gì đó, và sau đó 'khác' khi vòng lặp không bao giờ được thực thi.
Tor Valamo

258

Từ 2,5 trở đi có một phương pháp đặc biệt __missing__được gọi cho các mục bị thiếu:

>>> class MyDict(dict):
...  def __missing__(self, key):
...   self[key] = rv = []
...   return rv
... 
>>> m = MyDict()
>>> m["foo"].append(1)
>>> m["foo"].append(2)
>>> dict(m)
{'foo': [1, 2]}

Ngoài ra còn có một lớp con dict trong collectionsđược gọi là defaultdictkhá giống nhau nhưng gọi một hàm không có đối số cho các mục không tồn tại:

>>> from collections import defaultdict
>>> m = defaultdict(list)
>>> m["foo"].append(1)
>>> m["foo"].append(2)
>>> dict(m)
{'foo': [1, 2]}

Tôi khuyên bạn nên chuyển đổi các ký tự như vậy thành các ký tự thông thường trước khi chuyển chúng sang các hàm không mong đợi các lớp con như vậy. Rất nhiều mã sử dụng d[a_key]và bắt KeyErrors để kiểm tra xem một mục có tồn tại hay không sẽ thêm một mục mới vào dict.


10
Tôi thích sử dụng setdefault. m = {}; m.setdefault ('foo', 1)
Grayger

22
@grayger nghĩa là thế này m={}; m.setdefault('foo', []).append(1).
Cristian Ciupitu

1
Tuy nhiên, có những trường hợp thông qua defaultdict rất tiện dụng. Ví dụ, hàm có thể lặp lại giá trị và nó hoạt động cho các khóa không xác định mà không cần thêm mã, vì mặc định là một danh sách trống.
Mary

3
defaultdict trong một số trường hợp tốt hơn setdefault, vì nó không tạo đối tượng mặc định trừ khi thiếu khóa. setdefault tạo ra cho dù nó có thiếu hay không. Nếu đối tượng mặc định của bạn tốn kém để tạo thì đây có thể là một cú hích hiệu năng - Tôi đã tăng tốc đáng kể từ một chương trình chỉ bằng cách thay đổi tất cả các lệnh gọi setdefault.
Whatang

2
defaultdictcũng mạnh hơn setdefaultphương pháp trong các trường hợp khác. Ví dụ, đối với một đối trọng dd = collections.defaultdict(int) ... dd[k] += 1vs d.setdefault(k, 0) += 1.
Mike Graham

247

Trao đổi giá trị tại chỗ

>>> a = 10
>>> b = 5
>>> a, b
(10, 5)

>>> a, b = b, a
>>> a, b
(5, 10)

Phía bên phải của bài tập là một biểu thức tạo ra một bộ dữ liệu mới. Phía bên trái của bài tập ngay lập tức giải nén mà (không được ước tính) tuple cho các tên ab.

Sau khi gán, bộ dữ liệu mới không được ước tính và được đánh dấu để thu gom rác và các giá trị được ràng buộc abđã được hoán đổi.

Như đã lưu ý trong phần hướng dẫn Python về cấu trúc dữ liệu ,

Lưu ý rằng nhiều nhiệm vụ thực sự chỉ là sự kết hợp của đóng gói tuple và giải nén chuỗi.


1
Điều này có sử dụng nhiều bộ nhớ thực hơn so với cách truyền thống? Tôi đoán là do bạn đang tạo một tuple, thay vì chỉ một biến trao đổi
Nathan

75
Nó không sử dụng nhiều bộ nhớ hơn. Nó sử dụng ít hơn .. Tôi chỉ viết cả hai cách và giải mã mã byte .. trình biên dịch tối ưu hóa, như bạn hy vọng nó sẽ làm. kết quả dis cho thấy nó đang thiết lập các vars, và sau đó ROT_TWOing. ROT_TWO có nghĩa là 'hoán đổi hai vars stack cao nhất' ... Thực sự khá hấp dẫn.
hoàng gia

5
Bạn cũng vô tình chỉ ra một tính năng hay khác của Python, đó là bạn có thể ngầm tạo ra một bộ các mục chỉ bằng cách tách chúng bằng dấu phẩy.
asmeker

3
Dana the Sane: gán trong Python là một câu lệnh, không phải là biểu thức, vì vậy biểu thức đó sẽ không hợp lệ nếu = có mức độ ưu tiên cao hơn (nghĩa là nó được hiểu là a, (b = b), a).
hbn

5
Đây là tính năng ít bị ẩn nhất mà tôi đã đọc ở đây. Đẹp, nhưng được mô tả rõ ràng trong mỗi hướng dẫn Python.
Thiago Chaves

235

Biểu thức chính quy có thể đọc được

Trong Python, bạn có thể chia một biểu thức chính quy thành nhiều dòng, đặt tên cho các kết quả khớp của bạn và chèn nhận xét.

Ví dụ cú pháp verbose (từ Lặn vào Python ):

>>> pattern = """
... ^                   # beginning of string
... M{0,4}              # thousands - 0 to 4 M's
... (CM|CD|D?C{0,3})    # hundreds - 900 (CM), 400 (CD), 0-300 (0 to 3 C's),
...                     #            or 500-800 (D, followed by 0 to 3 C's)
... (XC|XL|L?X{0,3})    # tens - 90 (XC), 40 (XL), 0-30 (0 to 3 X's),
...                     #        or 50-80 (L, followed by 0 to 3 X's)
... (IX|IV|V?I{0,3})    # ones - 9 (IX), 4 (IV), 0-3 (0 to 3 I's),
...                     #        or 5-8 (V, followed by 0 to 3 I's)
... $                   # end of string
... """
>>> re.search(pattern, 'M', re.VERBOSE)

Ví dụ đặt tên khớp (từ Biểu thức thông thường HOWTO )

>>> p = re.compile(r'(?P<word>\b\w+\b)')
>>> m = p.search( '(((( Lots of punctuation )))' )
>>> m.group('word')
'Lots'

Bạn cũng có thể viết một cách chính xác một regex mà không cần sử dụng re.VERBOSEnhờ nối chuỗi theo nghĩa đen.

>>> pattern = (
...     "^"                 # beginning of string
...     "M{0,4}"            # thousands - 0 to 4 M's
...     "(CM|CD|D?C{0,3})"  # hundreds - 900 (CM), 400 (CD), 0-300 (0 to 3 C's),
...                         #            or 500-800 (D, followed by 0 to 3 C's)
...     "(XC|XL|L?X{0,3})"  # tens - 90 (XC), 40 (XL), 0-30 (0 to 3 X's),
...                         #        or 50-80 (L, followed by 0 to 3 X's)
...     "(IX|IV|V?I{0,3})"  # ones - 9 (IX), 4 (IV), 0-3 (0 to 3 I's),
...                         #        or 5-8 (V, followed by 0 to 3 I's)
...     "$"                 # end of string
... )
>>> print pattern
"^M{0,4}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})$"

7
Tôi không biết nếu tôi thực sự xem xét rằng một tính năng Python, hầu hết các công cụ RE đều có tùy chọn dài dòng.
Jeremy Banks

18
Có, nhưng vì bạn không thể làm điều đó trong grep hoặc trong hầu hết các biên tập viên, rất nhiều người không biết nó ở đó. Thực tế là các ngôn ngữ khác có một tính năng tương đương không làm cho nó không phải là một tính năng hữu ích và ít được biết đến của python
Mark Baker

7
Trong một dự án lớn với rất nhiều biểu thức chính quy được tối ưu hóa (đọc: được tối ưu hóa cho máy nhưng không phải là con người), tôi cắn viên đạn và chuyển đổi tất cả chúng thành cú pháp dài dòng. Bây giờ, giới thiệu các nhà phát triển mới cho các dự án dễ dàng hơn nhiều. Từ giờ trở đi, chúng tôi thi hành REs dài dòng trên mỗi dự án.
Berk D. Demir

Tôi chỉ muốn nói: trăm = "(CM | CD | D? C {0,3})" # 900 (CM), 400 (CD), v.v. Ngôn ngữ đã có cách đặt tên cho mọi thứ, a cách để thêm ý kiến ​​và cách kết hợp chuỗi. Tại sao sử dụng cú pháp thư viện đặc biệt ở đây cho những thứ mà ngôn ngữ đã làm hoàn toàn tốt? Nó dường như đi trực tiếp với Perlis 'Epigram 9.
Ken

3
@Ken: regex có thể không phải lúc nào cũng trực tiếp trong nguồn, nó có thể được đọc từ cài đặt hoặc tệp cấu hình. Cho phép bình luận hoặc chỉ khoảng trắng bổ sung (cho khả năng đọc) có thể là một trợ giúp tuyệt vời.

222

Chức năng giải nén đối số

Bạn có thể giải nén một danh sách hoặc một từ điển dưới dạng đối số chức năng bằng cách sử dụng ***.

Ví dụ:

def draw_point(x, y):
    # do some magic

point_foo = (3, 4)
point_bar = {'y': 3, 'x': 2}

draw_point(*point_foo)
draw_point(**point_bar)

Phím tắt rất hữu ích vì danh sách, bộ dữ liệu và dicts được sử dụng rộng rãi như các thùng chứa.


27
* còn được gọi là toán tử splat
Gabriel

3
Tôi thích tính năng này, nhưng pylint không buồn.
Stephen Paulger

5
lời khuyên của pylint không phải là một luật. Một cách khác, áp dụng (có thể gọi được, arg_seq, arg_map), không được dùng nữa kể từ 2.3.
Yann Vernier

1
Lời khuyên của pylint có thể không phải là luật, nhưng đó là lời khuyên tốt. Mã gỡ lỗi mà quá ham mê những thứ như thế này là địa ngục thuần túy. Như các ghi chú poster ban đầu, đây là một phím tắt hữu ích .
Andrew

2
Tôi đã thấy điều này được sử dụng trong mã một lần và tự hỏi nó đã làm gì. Thật không may, thật khó để google cho "Python **"
Fraser Graham

205

ROT13 là một mã hóa hợp lệ cho mã nguồn, khi bạn sử dụng khai báo mã hóa đúng ở đầu tệp mã:

#!/usr/bin/env python
# -*- coding: rot13 -*-

cevag "Uryyb fgnpxbiresybj!".rapbqr("rot13")

10
Tuyệt quá! Lưu ý cách các chuỗi byte được lấy theo nghĩa đen, nhưng các chuỗi unicode được giải mã: thửcevag h"Uryyb fgnpxbiresybj!"
u0b34a0f6ae

12
Thật không may, nó đã bị xóa khỏi py3k
mykhal

9
Điều này là tốt để bỏ qua phần mềm chống vi-rút.
L̲̳o̲̳̳n̲̳̳g̲̳̳p̲̳o̲̳̳k̲̳̳e̲̳̳

96
Điều đó không liên quan gì đến mã hóa, nó chỉ là Python được viết bằng tiếng Wales. :-P
Olivier Verdier

33
Ph'nglui mglw'nafh Cthulhu R'lyeh wgah'nagl fhtagn!
Manuel Ferreria

183

Tạo kiểu mới theo cách hoàn toàn năng động

>>> NewType = type("NewType", (object,), {"x": "hello"})
>>> n = NewType()
>>> n.x
"hello"

giống hệt như

>>> class NewType(object):
>>>     x = "hello"
>>> n = NewType()
>>> n.x
"hello"

Có lẽ không phải là điều hữu ích nhất, nhưng tốt đẹp để biết.

Chỉnh sửa : Tên cố định của loại mới, phải là NewTypechính xác giống như với classtuyên bố.

Chỉnh sửa : Điều chỉnh tiêu đề để mô tả chính xác hơn tính năng.


8
Điều này có rất nhiều tiềm năng về tính hữu dụng, ví dụ: ORM JIT
Mark Cidade

8
Tôi sử dụng nó để tạo các lớp Biểu mẫu HTML dựa trên đầu vào động. Rất đẹp!
pi.

15
Lưu ý: tất cả các lớp được tạo ra trong thời gian chạy. Vì vậy, bạn có thể sử dụng câu lệnh 'class' trong một điều kiện hoặc trong một hàm (rất hữu ích để tạo các họ của các lớp hoặc các lớp đóng vai trò là bao đóng). Cải tiến mà 'loại' mang lại là khả năng xác định gọn gàng một tập hợp các thuộc tính (hoặc cơ sở) được tạo động.
spookylukey

1
Bạn cũng có thể tạo các loại ẩn danh với một chuỗi trống như: type ('', (object,), {'x': 'blah'})
bluehavana

3
Có thể rất hữu ích cho việc tiêm mã.
Avihu Turzion

179

Trình quản lý bối cảnh và " with" Tuyên bố

Được giới thiệu trong PEP 343 , trình quản lý bối cảnh là một đối tượng hoạt động như bối cảnh thời gian chạy cho một bộ các câu lệnh.

Do tính năng này sử dụng các từ khóa mới, nên nó được giới thiệu dần dần: nó có sẵn trong Python 2.5 thông qua __future__chỉ thị. Python 2.6 trở lên (bao gồm cả Python 3) có sẵn theo mặc định.

Tôi đã sử dụng câu lệnh "với" rất nhiều vì tôi nghĩ đó là một cấu trúc rất hữu ích, đây là bản demo nhanh:

from __future__ import with_statement

with open('foo.txt', 'w') as f:
    f.write('hello!')

Điều xảy ra ở đây đằng sau hậu trường, đó là câu lệnh "với" gọi đặc biệt __enter____exit__các phương thức trên đối tượng tệp. Chi tiết ngoại lệ cũng được chuyển đến __exit__nếu có bất kỳ ngoại lệ nào được đưa ra từ phần thân với câu lệnh, cho phép xử lý ngoại lệ xảy ra ở đó.

Điều này làm cho bạn trong trường hợp cụ thể này là nó đảm bảo rằng tệp được đóng khi thực thi nằm ngoài phạm vi của withbộ phần mềm, bất kể điều đó xảy ra bình thường hay có ném ngoại lệ hay không. Về cơ bản, đây là một cách để trừu tượng hóa mã xử lý ngoại lệ phổ biến.

Các trường hợp sử dụng phổ biến khác cho việc này bao gồm khóa với các luồng và giao dịch cơ sở dữ liệu.


3
Tôi sẽ không phê duyệt đánh giá mã đã nhập bất cứ thứ gì từ tương lai . Các tính năng dễ thương hơn hữu ích và thường chúng chỉ gây nhầm lẫn cho những người mới sử dụng Python.
một mọt sách được trả tiền

6
Vâng, các tính năng "dễ thương" như phạm vi lồng nhau và máy phát điện sẽ tốt hơn cho những người biết họ đang làm gì. Và bất cứ ai muốn tương thích với các phiên bản Python trong tương lai. Đối với phạm vi và trình tạo lồng nhau, "phiên bản tương lai" của Python có nghĩa lần lượt là 2.2 và 2.5. Đối với câu lệnh with, "phiên bản tương lai" của Python có nghĩa là 2.6.
Chris B.

10
Điều này có thể không cần phải nói, nhưng với python v2.6 +, bạn không còn cần phải nhập từ tương lai . bây giờ là một từ khóa hạng nhất.
fitzgeraldsteele

25
Trong 2.7 bạn có thể có nhiều withs:) with open('filea') as filea and open('fileb') as fileb: ...
Austin Richardson

5
@Austin tôi không thể sử dụng cú pháp đó để làm việc trên 2.7. tuy nhiên điều này đã làm việc: with open('filea') as filea, open('fileb') as fileb: ...
wim

168

Từ điển có một phương thức get ()

Từ điển có phương thức 'get ()'. Nếu bạn làm d ['key'] và khóa không có ở đó, bạn sẽ có một ngoại lệ. Nếu bạn làm d.get ('key'), bạn sẽ nhận lại Không nếu 'key' không có ở đó. Bạn có thể thêm một đối số thứ hai để lấy lại mục đó thay vì Không, ví dụ: d.get ('key', 0).

Thật tuyệt vời cho những thứ như thêm số:

sum[value] = sum.get(value, 0) + 1


39
Ngoài ra, kiểm tra phương thức setdefault.
Daren Thomas

27
Ngoài ra, kiểm tra bộ sưu tập lớp.defaultdict.
jfs

8
Nếu bạn đang sử dụng Python 2.7 trở lên, hoặc 3.1 trở lên, hãy xem lớp Counter trong mô-đun bộ sưu tập. docs.python.org/library/collections.html#collections.Counter
Elias Zamaria

Ôi trời, toàn bộ thời gian này tôi đã làm get(key, None). Không có ý tưởng Noneđược cung cấp theo mặc định.
Jordan Reiter

152

Mô tả

Chúng là ma thuật đằng sau một loạt các tính năng cốt lõi của Python.

Khi bạn sử dụng quyền truy cập rải rác để tra cứu thành viên (ví dụ: xy), trước tiên Python sẽ tìm thành viên trong từ điển ví dụ. Nếu nó không được tìm thấy, nó sẽ tìm nó trong từ điển lớp. Nếu nó tìm thấy nó trong từ điển lớp và đối tượng thực hiện giao thức mô tả, thay vì chỉ trả về nó, Python sẽ thực thi nó. Một mô tả là bất kỳ lớp thực hiện __get__, __set__hoặc __delete__phương pháp.

Đây là cách bạn triển khai phiên bản tài sản (chỉ đọc) của riêng bạn bằng cách sử dụng các mô tả:

class Property(object):
    def __init__(self, fget):
        self.fget = fget

    def __get__(self, obj, type):
        if obj is None:
            return self
        return self.fget(obj)

và bạn sẽ sử dụng nó giống như thuộc tính tích hợp ():

class MyClass(object):
    @Property
    def foo(self):
        return "Foo!"

Các mô tả được sử dụng trong Python để thực hiện các thuộc tính, phương thức ràng buộc, phương thức tĩnh, phương thức lớp và vị trí, trong số những thứ khác. Hiểu chúng giúp bạn dễ dàng nhận ra lý do tại sao rất nhiều thứ trước đây trông giống như 'quirks' của Python là như vậy.

Raymond Hettinger có một hướng dẫn tuyệt vời thực hiện công việc mô tả chúng tốt hơn nhiều so với tôi.


Đây là một bản sao của trang trí, phải không!? ( stackoverflow.com/questions/101268/
Mạnh

2
không, trang trí và mô tả là những thứ hoàn toàn khác nhau, mặc dù trong mã ví dụ, tôi đang tạo ra một trang trí mô tả. :)
Nick Johnson

1
Một cách khác để làm điều này là với lambda:foo = property(lambda self: self.__foo)
Pete Peterson

1
@PetePeterson Có, nhưng propertybản thân nó được triển khai với các mô tả, đó là điểm của bài viết của tôi.
Nick Johnson

142

Chuyển nhượng có điều kiện

x = 3 if (y == 1) else 2

Nó thực hiện chính xác những gì nó nghe như: "gán 3 cho x nếu y là 1, nếu không thì gán 2 cho x". Lưu ý rằng các parens là không cần thiết, nhưng tôi thích chúng cho dễ đọc. Bạn cũng có thể xâu chuỗi nó nếu bạn có một cái gì đó phức tạp hơn:

x = 3 if (y == 1) else 2 if (y == -1) else 1

Mặc dù tại một thời điểm nhất định, nó đi quá xa.

Lưu ý rằng bạn có thể sử dụng nếu ... khác trong bất kỳ biểu thức nào. Ví dụ:

(func1 if y == 1 else func2)(arg1, arg2) 

Ở đây func1 sẽ được gọi nếu y là 1 và func2, nếu không. Trong cả hai trường hợp, hàm tương ứng sẽ được gọi với các đối số arg1 và arg2.

Tương tự, những điều sau đây cũng hợp lệ:

x = (class1 if y == 1 else class2)(arg1, arg2)

trong đó class1 và class2 là hai lớp.


29
Nhiệm vụ không phải là phần đặc biệt. Bạn có thể dễ dàng làm điều gì đó như: return 3 if (y == 1) khác 2.
Brian

25
Cách thay thế đó là lần đầu tiên tôi thấy Python bị xáo trộn.
Craig McQueen

3
Kylebrooks: Không phải trong trường hợp đó, các nhà khai thác boolean bị đoản mạch. Nó sẽ chỉ đánh giá 2 nếu bool (3) == Sai.
RoadieRich

15
mã hóa kiểu ngược này làm tôi bối rối. một cái gì đó x = ((y == 1) ? 3 : 2)có ý nghĩa hơn đối với tôi
mpen

13
Tôi cảm thấy ngược lại với @Mark, các nhà khai thác ternary kiểu C luôn làm tôi bối rối, là bên phải hay giữa những gì được đánh giá trên một điều kiện sai? Tôi rất thích cú pháp ternary của Python.
Jeffrey Harris

141

Doctest : tài liệu và kiểm tra đơn vị cùng một lúc.

Ví dụ được trích xuất từ ​​tài liệu Python:

def factorial(n):
    """Return the factorial of n, an exact integer >= 0.

    If the result is small enough to fit in an int, return an int.
    Else return a long.

    >>> [factorial(n) for n in range(6)]
    [1, 1, 2, 6, 24, 120]
    >>> factorial(-1)
    Traceback (most recent call last):
        ...
    ValueError: n must be >= 0

    Factorials of floats are OK, but the float must be an exact integer:
    """

    import math
    if not n >= 0:
        raise ValueError("n must be >= 0")
    if math.floor(n) != n:
        raise ValueError("n must be exact integer")
    if n+1 == n:  # catch a value like 1e300
        raise OverflowError("n too large")
    result = 1
    factor = 2
    while factor <= n:
        result *= factor
        factor += 1
    return result

def _test():
    import doctest
    doctest.testmod()    

if __name__ == "__main__":
    _test()

6
Doctests chắc chắn rất tuyệt, nhưng tôi thực sự không thích tất cả các hành trình bạn phải gõ để kiểm tra xem có thứ gì đó nên đưa ra một ngoại lệ
TM.

60
Tài liệu được đánh giá cao và gây ô nhiễm tài liệu. Tần suất bạn kiểm tra một hàm độc lập mà không có bất kỳ setUp () nào?
một mọt sách được trả tiền

2
Ai nói bạn không thể thiết lập trong một doctest? viết một hàm tạo ra bối cảnh và trả về locals()sau đó trong doctest của bạn do locals().update(setUp())= D
Jiaaro

12
Nếu một hàm độc lập yêu cầu một setUp, rất có thể nó sẽ được tách rời khỏi một số thứ không liên quan hoặc đưa vào một lớp. Không gian tên doctest lớp sau đó có thể được sử dụng lại trong doctest phương thức lớp, do đó, nó hơi giống với setUp, chỉ DRY và có thể đọc được.
Andy Mikhaylenko

4
"Tần suất bạn kiểm tra một chức năng độc lập" - rất nhiều. Tôi thấy các tài liệu thường xuất hiện một cách tự nhiên từ quá trình thiết kế khi tôi quyết định mặt tiền.
Gregg Lind

138

Định dạng được đặt tên

% -formatted mất một từ điển (cũng áp dụng xác nhận% i /% s, v.v.).

>>> print "The %(foo)s is %(bar)i." % {'foo': 'answer', 'bar':42}
The answer is 42.

>>> foo, bar = 'question', 123

>>> print "The %(foo)s is %(bar)i." % locals()
The question is 123.

Và vì locals () cũng là một từ điển, bạn chỉ có thể chuyển nó dưới dạng chính tả và có% -substitions từ các biến cục bộ của bạn. Tôi nghĩ rằng điều này được tán thành, nhưng đơn giản hóa mọi thứ ..

Định dạng kiểu mới

>>> print("The {foo} is {bar}".format(foo='answer', bar=42))

60
Sẽ được loại bỏ dần và cuối cùng được thay thế bằng phương thức format () của chuỗi.
Constantin

3
Định dạng được đặt tên rất hữu ích cho người dịch vì họ có xu hướng chỉ nhìn thấy chuỗi định dạng mà không có tên biến cho ngữ cảnh
pixelbeat

2
Xuất hiện để hoạt động trong python 3.0.1 (cần thiết để thêm các ngoặc đơn xung quanh lệnh in).
Pasi Savolainen

9
một băm , huh? Tôi thấy bạn đến từ đâu.
shylent

11
Định dạng% s sẽ không được loại bỏ. str.format () chắc chắn là nhiều pythonic hơn, tuy nhiên thực tế là chậm hơn 10 lần đối với việc thay thế chuỗi đơn giản. Niềm tin của tôi là định dạng% s vẫn là thực hành tốt nhất.
Kenneth Reitz

132

Để thêm nhiều mô-đun python (đặc biệt là bên thứ 3), hầu hết mọi người dường như sử dụng các biến môi trường PYTHONPATH hoặc họ thêm symlink hoặc thư mục trong thư mục gói trang web của họ. Một cách khác, là sử dụng các tệp * .pth. Đây là lời giải thích chính thức của python doc:

"Cách thuận tiện nhất [để sửa đổi đường dẫn tìm kiếm của python] là thêm tệp cấu hình đường dẫn vào thư mục đã có trên đường dẫn của Python, thường là vào thư mục ... / site-gói / thư mục. Các tệp cấu hình đường dẫn có phần mở rộng là .pth và mỗi dòng phải chứa một đường dẫn sẽ được thêm vào sys.path. (Vì các đường dẫn mới được thêm vào sys.path, các mô-đun trong các thư mục đã thêm sẽ không ghi đè các mô-đun chuẩn. Điều này có nghĩa là bạn không thể sử dụng cơ chế này để cài đặt các phiên bản cố định của các mô-đun tiêu chuẩn.) "


1
Tôi chưa bao giờ thực hiện kết nối giữa tệp .pth đó trong thư mục gói trang web từ setuptools và ý tưởng này. tuyệt vời.
dave paola

122

Mệnh đề ngoại lệ khác :

try:
  put_4000000000_volts_through_it(parrot)
except Voom:
  print "'E's pining!"
else:
  print "This parrot is no more!"
finally:
  end_sketch()

Việc sử dụng mệnh đề khác tốt hơn là thêm mã bổ sung vào mệnh đề try vì nó tránh vô tình bắt gặp một ngoại lệ không được nêu ra bởi mã được bảo vệ bởi lệnh thử ... ngoại trừ câu lệnh.

Xem http://docs.python.org/tut/node10.html


8
+1 điều này thật tuyệt vời. Nếu khối thử thực thi mà không nhập bất kỳ khối ngoại lệ nào, thì khối khác được nhập. Và dĩ nhiên, khối cuối cùng được thực thi
InspectorG4dget

Cuối cùng tôi cũng hiểu tại sao 'cái khác' lại ở đó! Cảm ơn.
taynaron

Nó sẽ có ý nghĩa hơn để sử dụng tiếp tục, nhưng tôi đoán nó đã được sử dụng;)
Paweł Prażak

Lưu ý rằng trên các phiên bản cũ hơn của Python2, bạn không thể có cả hai thứ khác: và cuối cùng: các mệnh đề cho cùng một lần thử: khối
Kevin Horn

1
@ Paweł Prażak, như Kevin Horn đã đề cập, cú pháp này được giới thiệu sau khi phát hành Python ban đầu và việc thêm các từ khóa dành riêng mới vào ngôn ngữ hiện tại luôn có vấn đề. Đó là lý do tại sao một từ khóa hiện tại thường được sử dụng lại (cf "auto" trong tiêu chuẩn C ++ gần đây).
Constantin

114

Nâng cao ngoại lệ :

# Python 2 syntax
try:
    some_operation()
except SomeError, e:
    if is_fatal(e):
        raise
    handle_nonfatal(e)

# Python 3 syntax
try:
    some_operation()
except SomeError as e:
    if is_fatal(e):
        raise
    handle_nonfatal(e)

Câu lệnh 'nâng cao' không có đối số bên trong trình xử lý lỗi yêu cầu Python nêu lại ngoại lệ với nguyên bản truy nguyên gốc , cho phép bạn nói "oh, xin lỗi, xin lỗi, tôi không có ý bắt nó, xin lỗi, xin lỗi. "

Nếu bạn muốn in, lưu trữ hoặc fiddle với tracBack gốc, bạn có thể lấy nó bằng sys.exc_info () và in nó như Python sẽ được thực hiện với mô-đun 'tracBack'.


Xin lỗi nhưng đây là một tính năng nổi tiếng và phổ biến của hầu hết các ngôn ngữ.
Lucas S.

6
Lưu ý văn bản in nghiêng. Một số người sẽ làm raise ethay vào đó, điều này không giữ được dấu vết ban đầu.
thói quen

12
Có thể kỳ diệu hơn, exc_info = sys.exc_info(); raise exc_info[0], exc_info[1], exc_info[2]tương đương với điều này, nhưng bạn có thể thay đổi các giá trị đó xung quanh (ví dụ: thay đổi loại ngoại lệ hoặc tin nhắn)
ianb

3
@Lucas S. Chà, tôi không biết điều đó và tôi rất vui vì nó được viết ở đây.
e-satis

Tôi có thể thể hiện tuổi trẻ của mình ở đây, nhưng tôi đã luôn sử dụng cú pháp python 3 trong python 2.7 mà không có vấn đề gì
wim

106

Tin nhắn chính :)

import this
# btw look at this module's source :)

Khử nhiễu :

Zen của Python, bởi Tim Peters

Đẹp thì tốt hơn xấu.
Rõ ràng là tốt hơn so với ngầm.
Đơn giản là tốt hơn phức tạp.
Phức tạp tốt hơn phức tạp.
Bằng phẳng là tốt hơn so với lồng nhau.
Thưa thì tốt hơn dày đặc.
Tính dễ đọc.
Trường hợp đặc biệt không đủ đặc biệt để phá vỡ các quy tắc.
Mặc dù thực tế đánh bại sự tinh khiết.
Lỗi không bao giờ nên âm thầm vượt qua.
Trừ khi im lặng rõ ràng.
Trước sự mơ hồ, hãy từ chối sự cám dỗ để đoán. Nên có một-- và tốt nhất là chỉ có một cách rõ ràng để làm điều đó.
Mặc dù cách đó ban đầu có thể không rõ ràng trừ khi bạn là người Hà Lan.
Bây giờ tốt hơn bao giờ hết.
Mặc dù không bao giờ thường tốt hơnngay bây giờ
Nếu việc thực hiện khó giải thích, đó là một ý tưởng tồi.
Nếu việc thực hiện dễ giải thích, nó có thể là một ý tưởng tốt.
Không gian tên là một ý tưởng tuyệt vời - hãy làm nhiều hơn nữa!


1
Bất cứ ý tưởng tại sao các nguồn đã được cyphered theo cách đó? Có phải chỉ để cho vui, hoặc có một số lý do khác?
MiniQuark

42
cách viết nguồn đi ngược lại với zen!
hasen


2
Tôi đã cập nhật /usr/lib/python2.6/this.py thay thế mã cũ bằng mã này print s.translate("".join(chr(64<i<91 and 65+(i-52)%26 or 96<i<123 and 97+(i-84)%26 or i) for i in range(256)))và giờ nó có vẻ tốt hơn nhiều !! :-D
fortran

2
@MiniQuark: bài học lịch sử nhanh: wefearchange.org/2010/06/import-this-and-zen-of-python.html

105

Hoàn thành tab phiên dịch tương tác

try:
    import readline
except ImportError:
    print "Unable to load readline module."
else:
    import rlcompleter
    readline.parse_and_bind("tab: complete")


>>> class myclass:
...    def function(self):
...       print "my function"
... 
>>> class_instance = myclass()
>>> class_instance.<TAB>
class_instance.__class__   class_instance.__module__
class_instance.__doc__     class_instance.function
>>> class_instance.f<TAB>unction()

Bạn cũng sẽ phải đặt biến môi trường PYTHONSTARTUP.


2
Đây là một tính năng rất hữu ích. Rất nhiều vì vậy tôi đã có một tập lệnh đơn giản để kích hoạt nó (cộng với một vài cải tiến hướng nội khác): pixelbeat.org/scripts/inpy
pixelbeat

43
IPython cung cấp cho bạn điều này cộng với hàng tấn những thứ gọn gàng khác
akaihola

Điều này sẽ hữu ích hơn ở dấu nhắc pdb so với dấu nhắc python thông thường (vì IPython vẫn phục vụ mục đích đó). Tuy nhiên, điều này dường như không hoạt động tại dấu nhắc pdb, có thể là do pdb liên kết riêng cho tab (ít hữu ích hơn). Tôi đã thử gọi parse_and_bind () tại dấu nhắc pdb, nhưng nó vẫn không hoạt động. Việc thay thế để nhận được nhắc pdb với IPython là công việc nhiều hơn vì vậy tôi có xu hướng không sử dụng nó.
haridsv

2
@haridsv - easy_install ipdb- sau đó bạn có thể sử dụngimport ipdb; ipdb.set_trace()
Doug Harris

1
Trên osx [và tôi tưởng tượng các hệ thống khác sử dụng libedit] bạn phải làmreadline.parse_and_bind ("bind ^I rl_complete")
Foo Bah

91

Hiểu danh sách lồng nhau và biểu thức trình tạo:

[(i,j) for i in range(3) for j in range(i) ]    
((i,j) for i in range(4) for j in range(i) )

Chúng có thể thay thế các khối lớn của mã vòng lặp lồng nhau.


"cho j trong phạm vi (i)" - đây có phải là một lỗi đánh máy không? Thông thường bạn muốn phạm vi cố định cho i và j. Nếu bạn đang truy cập mảng 2d, bạn sẽ bỏ lỡ một nửa các yếu tố của mình.
Peter Gibson

Tôi không truy cập bất kỳ mảng nào trong ví dụ này. Mục đích duy nhất của mã này là chỉ ra rằng các biểu thức từ các phạm vi bên trong có thể truy cập các biểu thức từ các phạm vi bên ngoài. Sản phẩm phụ là danh sách các cặp (x, y) sao cho 4> x> y> 0.
Rafał Dowgird

2
sắp xếp như tích hợp kép trong tính toán, hoặc tổng hai lần.
Yoo

22
Điểm quan trọng cần nhớ ở đây (điều này khiến tôi mất nhiều thời gian để nhận ra) là thứ tự của các forcâu lệnh sẽ được viết theo thứ tự mà bạn mong đợi chúng được viết theo vòng lặp tiêu chuẩn, từ bên ngoài vào trong.
sykora

2
Để thêm vào nhận xét của sykora: hãy tưởng tượng bạn đang bắt đầu với một chồng fors và ifs yield xbên trong. Để chuyển đổi biểu thức đó thành biểu thức trình tạo, di chuyển xtrước, xóa tất cả các dấu hai chấm (và dấu yield) và bao quanh toàn bộ trong ngoặc đơn. Để thực hiện một sự hiểu biết danh sách thay thế, thay thế các dấu ngoặc ngoài bằng dấu ngoặc vuông.
Ken Arnold

91

Toán tử quá tải cho tích hợp set:

>>> a = set([1,2,3,4])
>>> b = set([3,4,5,6])
>>> a | b # Union
{1, 2, 3, 4, 5, 6}
>>> a & b # Intersection
{3, 4}
>>> a < b # Subset
False
>>> a - b # Difference
{1, 2}
>>> a ^ b # Symmetric Difference
{1, 2, 5, 6}

Chi tiết hơn từ tài liệu tham khảo thư viện tiêu chuẩn: Đặt loại


Trong hướng dẫn, một phần docs.python.org/tutorial/datastructures.html#sets
XTL
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.