In một danh sách theo thứ tự ngược với phạm vi ()?


364

Làm thế nào bạn có thể tạo danh sách sau đây với range()bằng Python?

[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]

Còn [* phạm vi (9, -1, -1)] thì sao? Siêu trăn!
onofricamila

Câu trả lời:


561

sử dụng reversed()chức năng:

reversed(range(10))

Nó có ý nghĩa hơn nhiều.

Cập nhật:

Nếu bạn muốn nó là một danh sách (như btk đã chỉ ra):

list(reversed(range(10)))

Cập nhật:

Nếu bạn chỉ muốn sử dụng rangeđể đạt được kết quả tương tự, bạn có thể sử dụng tất cả các tham số của nó.range(start, stop, step)

Ví dụ: để tạo danh sách [5,4,3,2,1,0], bạn có thể sử dụng như sau:

range(5, -1, -1)

Nó có thể ít trực quan hơn nhưng như các ý kiến ​​đề cập, điều này hiệu quả hơn và sử dụng đúng phạm vi cho danh sách đảo ngược.


13
Mặc dù nó 'kém hiệu quả hơn. Và bạn không thể thực hiện các thao tác cắt trên nó.
Jakob Bowyer

6
Câu trả lời này rất rõ ràng và dễ hiểu, nhưng nó cần phải range(10), không phải range(9). Ngoài ra, nếu bạn muốn một danh sách đầy đủ (để cắt, v.v.), bạn nên làm list(reversed(range(10))).
John Y

5
Điều này tạo ra một trình vòng lặp, OP yêu cầu một kết quả dưới dạng một danh sách.
btk

6
Việc sử dụng "đảo ngược" với trình tạo python (giả sử chúng ta nói về phạm vi tích hợp Python 3) là sai về mặt khái niệm và dạy các thói quen sai lầm khi không xem xét độ phức tạp của bộ nhớ / xử lý khi lập trình bằng ngôn ngữ cấp cao.
thedk

7
Trong Python3, reversedkhông chấp nhận các trình tạo nói chung nhưng nó chấp nhận range. Tại sao reversed(range(10000))cần phân bổ bộ nhớ cho toàn bộ danh sách? rangecó thể trả về một đối tượng thực hiện __reversed__phương thức cho phép lặp ngược hiệu quả không?
avmohan

312

Sử dụng chức năng tích hợp 'phạm vi'. Chữ ký là range(start, stop, step). Điều này tạo ra một chuỗi mang lại các số, bắt đầu bằng startvà kết thúc nếu stopđã đạt được, ngoại trừ stop.

>>> range(9,-1,-1)   
    [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
>>> range(-2, 6, 2)
    [-2, 0, 2, 4]

Trong Python 3, điều này tạo ra một rangeđối tượng không có danh sách , hoạt động hiệu quả như danh sách chỉ đọc (nhưng sử dụng ít bộ nhớ hơn, đặc biệt là cho phạm vi lớn).


1
Bạn có thể vui lòng giải thích điều này không, bạn cũng có thể vui lòng giới thiệu cho tôi bất kỳ trang web / sách pdf nào cho python
ramesh.mimit

8
@ramesh Nếu bạn chạy help(range)trong shell python, nó sẽ cho bạn biết các đối số. Chúng là số bắt đầu, số kết thúc (độc quyền) và bước cần thực hiện, vì vậy nó bắt đầu từ 9 và trừ 1 cho đến khi đến -1 (tại thời điểm nó dừng mà không quay lại, đó là lý do tại sao phạm vi kết thúc lúc 0)
Michael Mrozek

3
@ ramesh.mimit: Chỉ cần truy cập trang web Python chính thức. Có tài liệu đầy đủ ở đó, bao gồm một hướng dẫn tuyệt vời.
John Y

5
Thực sự, đây là câu trả lời thích hợp, nhưng nó có thể được giải thích rõ ràng hơn. range(start, stop, step) - bắt đầu ở số startvà mang lại kết quả trừ khi stopđạt được, di chuyển theo steptừng thời điểm.
Ông B

43

Bạn có thể sử dụng range(10)[::-1]đó là điều tương tự range(9, -1, -1)và dễ đọc hơn (nếu bạn quen thuộc với sequence[::-1]thành ngữ Python thông dụng ).


28

Đối với những người quan tâm đến "hiệu quả" của các tùy chọn được thu thập cho đến nay ...

Câu trả lời của Jaime RGP đã khiến tôi khởi động lại máy tính của mình sau khi định thời cho giải pháp hơi "thách thức" của Jason theo nghĩa đen của tôi (thông qua nhận xét). Để giảm bớt sự tò mò của bạn về thời gian chết, tôi trình bày ở đây kết quả của tôi (tồi tệ nhất trước tiên):

Câu trả lời của Jason (có thể chỉ là một chuyến tham quan vào sức mạnh của việc hiểu danh sách ):

$ python -m timeit "[9-i for i in range(10)]"
1000000 loops, best of 3: 1.54 usec per loop

câu trả lời của martineau (có thể đọc được nếu bạn quen thuộc với cú pháp lát mở rộng ):

$ python -m timeit "range(10)[::-1]"
1000000 loops, best of 3: 0.743 usec per loop

Câu trả lời của Michał Šrajer's ( câu được chấp nhận, rất dễ đọc):

$ python -m timeit "reversed(range(10))"
1000000 loops, best of 3: 0.538 usec per loop

câu trả lời của Bene (lần đầu tiên, nhưng rất sơ sài vào thời điểm đó ):

$ python -m timeit "range(9,-1,-1)"
1000000 loops, best of 3: 0.401 usec per loop

Tùy chọn cuối cùng rất dễ nhớ bằng cách sử dụng range(n-1,-1,-1)ký hiệu của Val Neekman .


3
Tôi đã thực hiện thời gian của riêng mình trước khi đọc câu trả lời này và nhận được kết quả tương tự.
Todd Owen

13
for i in range(8, 0, -1)

sẽ giải quyết vấn đề này. Nó sẽ xuất 8 thành 1 và -1 có nghĩa là một danh sách đảo ngược


10

Không có ý nghĩa để sử dụng reversebởi vì phương thức phạm vi có thể trả về danh sách đảo ngược.

Khi bạn có số lần lặp trên n mục và muốn thay thế thứ tự danh sách mà range(start, stop, step)bạn trả về, bạn phải sử dụng tham số thứ ba của phạm vi xác định stepvà đặt thành mục -1, các tham số khác sẽ được điều chỉnh tương ứng:

  1. Cung cấp tham số dừng dưới dạng -1(giá trị trước đó của stop - 1, stopbằng 0).
  2. Khi bắt đầu sử dụng tham số n-1.

Vì vậy, tương đương với phạm vi (n) theo thứ tự ngược lại sẽ là:

n = 10
print range(n-1,-1,-1) 
#[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]

6
Thành thật mà nói tôi thấy điều này ít trực quan hơnreversed(range(n))
Nicholas Hamilton

1
@Nicholas Hamilton Đồng ý với bạn, tuy nhiên ý tưởng đằng sau câu trả lời đó là sử dụng ít tài nguyên hơn ... (và câu hỏi là về việc chỉ sử dụng chức năng phạm vi :))
Andriy Ivaneyko

Ok, không phải lo lắng, tôi đoán nó phụ thuộc vào tình hình. Chẳng hạn, nếu hàm phạm vi được sử dụng làm chỉ mục cho một vòng lặp, thì nó sẽ có hiệu lực hạn chế, tuy nhiên, nếu nó được sử dụng bên trong một vòng lặp bên ngoài, thì chi phí sẽ gộp lại ...
Nicholas Hamilton

8

Dễ đọc sang một bên, reversed(range(n))dường như là nhanh hơn range(n)[::-1].

$ python -m timeit "reversed(range(1000000000))"
1000000 loops, best of 3: 0.598 usec per loop
$ python -m timeit "range(1000000000)[::-1]"
1000000 loops, best of 3: 0.945 usec per loop

Chỉ cần có ai thắc mắc :)


tốt để có một số số :) - tại sao bạn không thêm range(1000000000-1,-1,-1)vào?
Sói

... tốt hơn đừng thử timeit range(1000000000-1,-1,-1)trên dòng lệnh, thay vào đó hãy xem kết quả của tôi :-)
Wolf

6

Yêu cầu trong câu hỏi này yêu cầu một listsố nguyên có kích thước 10 theo thứ tự giảm dần. Vì vậy, hãy tạo ra một danh sách trong python.

# This meets the requirement.
# But it is a bit harder to wrap one's head around this. right?
>>> range(10-1, -1, -1)
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]

# let's find something that is a bit more self-explanatory. Sounds good?
# ----------------------------------------------------

# This returns a list in ascending order.
# Opposite of what the requirement called for.
>>> range(10)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

# This returns an iterator in descending order.
# Doesn't meet the requirement as it is not a list.
>>> reversed(range(10))
<listreverseiterator object at 0x10e14e090>

# This returns a list in descending order and meets the requirement
>>> list(reversed(range(10)))
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]

2
Tôi thực sự thích bộ ba-1 Chính xác là mẫu này giúp dễ dàng giữ wrap one's head around this- Hôm nay tôi đã học được rằng nếu nó thực sự phải hiệu quả , hãy sử dụng range(n-1, -1, -1)khi đi qua một phạm vi theo thứ tự đảo ngược.
Sói

5

Bạn có thể in các số ngược với phạm vi () BIF Thích,

for number in range ( 10 , 0 , -1 ) :
    print ( number ) 

Đầu ra sẽ là [10,9,8,7,6,5,4,3,2,1]

phạm vi () - phạm vi (bắt đầu, kết thúc, tăng / giảm) trong đó bắt đầu bao gồm, kết thúc là độc quyền và gia tăng có thể là bất kỳ số nào và hoạt động như bước


5

Câu hỏi thường gặp là liệu có range(9, -1, -1)tốt hơn reversed(range(10))trong Python 3 không? Những người đã làm việc trong các ngôn ngữ khác với các trình vòng lặp ngay lập tức có xu hướng nghĩ rằng đảo ngược () phải lưu trữ tất cả các giá trị và sau đó trả về theo thứ tự ngược lại. Điều đó là reversed()toán tử của Python không hoạt động nếu đối tượng chỉ là một trình vòng lặp. Đối tượng phải có một trong hai bên dưới để đảo ngược () để hoạt động:

  1. Hỗ trợ len()và chỉ mục số nguyên thông qua[]
  2. Hoặc có __reversed__()phương pháp thực hiện.

Nếu bạn cố gắng sử dụng Reverse () trên đối tượng không có mục nào ở trên thì bạn sẽ nhận được:

>>> [reversed((x for x in range(10)))]
TypeError: 'generator' object is not reversible

Vì vậy, trong ngắn hạn, Python reversed()chỉ có nghĩa là trên các mảng như các đối tượng và do đó, nó sẽ có hiệu suất tương tự như phép lặp tiến.

Nhưng còn cái gì range()? Đó không phải là một máy phát điện sao? Trong Python 3, nó là trình tạo nhưng được bao bọc trong một lớp thực hiện cả hai điều trên. Vì vậy, range(100000)không chiếm nhiều bộ nhớ nhưng nó vẫn hỗ trợ lập chỉ mục và đảo ngược hiệu quả.

Vì vậy, tóm lại, bạn có thể sử dụng reversed(range(10))mà không có bất kỳ cú đánh nào về hiệu suất.


3

tôi tin rằng điều này có thể giúp đỡ,

range(5)[::-1]

dưới đây là cách sử dụng:

for i in range(5)[::-1]:
    print i 

3
range(9,-1,-1)
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]

13
Câu trả lời của bạn cho thấy tại sao reversed(range(10))ít bị lỗi hơn. Không vi phạm Asinox. Chỉ là một quan sát trung thực.
Michał rajer

Tôi không biết có phải là tiêu chuẩn để để lại câu trả lời sai trên màn hình không. Tôi có thể hoặc ai đó sửa nó hoặc thậm chí loại bỏ nó?
sinekonata

3
@sine, nope chỉ để lại nó và tự hỏi làm thế nào nó tích lũy 3 upvotes ... Tôi cho rằng bạn có thể gắn cờ để ý điều hành (bản sao của câu trả lời từ 18 tháng trước đó, ngoại trừ bị hỏng), không chắc chắn dù có hoặc không muốn xóa nó.
OGHaza

Đối với tất cả các tham chiếu trong tương lai: chỉ mã không phải là VLQ và các câu trả lời sai cũng không được gắn cờ . Downvote và di chuyển trên, nhưng gắn cờ là sai trong trường hợp này, cho dù là NAA hay gắn cờ mod. - Từ đánh giá
Zoe

2

Sử dụng mà không có [:: - 1] hoặc đảo ngược -

def reverse(text):
    result = []
    for index in range(len(text)-1,-1,-1):
        c = text[index]
        result.append(c)
    return ''.join(result)

print reverse("python!")

6
Tại sao ai đó nên viết điều này thay vì "python!"[::-1]?
Daniel

1
[9-i for i in range(10)]
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]

1

Bạn không nhất thiết phải sử dụng chức năng phạm vi, bạn chỉ cần thực hiện danh sách [:: - 1] để trả về danh sách theo thứ tự đảo ngược nhanh chóng mà không cần sử dụng bất kỳ bổ sung nào.


Đây dường như là giải pháp được đề xuất trong câu trả lời trước . Cũng có vẻ như bạn có thể đang cố gắng nhận xét về một câu trả lời khác trước đó - bạn sẽ cần có thêm một chút danh tiếng trước khi bạn có thể làm điều đó.
Grisha Levit

1

Giả sử bạn có một danh sách gọi nó là a = {1,2,3,4,5} Bây giờ nếu bạn muốn in danh sách ngược lại thì chỉ cần sử dụng mã sau đây.

a.reverse
for i in a:
   print(i)

Tôi biết bạn đã hỏi sử dụng phạm vi nhưng nó đã được trả lời.


0
range(9,-1,-1)
    [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]

Là hình thức chính xác. Nếu bạn dùng

reversed(range(10))

bạn sẽ không nhận được một trường hợp 0. Chẳng hạn, giả sử số 10 của bạn không phải là số ma thuật và biến bạn đang sử dụng để tra cứu bắt đầu từ đảo ngược. Nếu trường hợp n của bạn là 0, đảo ngược (phạm vi (0)) sẽ không thực thi, đó là sai nếu bạn tình cờ có một đối tượng duy nhất trong chỉ mục 0.


0

Tôi nghĩ rằng nhiều người (như bản thân tôi) có thể quan tâm nhiều hơn đến một trường hợp phổ biến là duyệt qua một danh sách hiện có theo thứ tự đảo ngược thay vào đó, như đã nêu trong tiêu đề, thay vì chỉ tạo ra các chỉ số cho giao dịch đó.

Mặc dù, tất cả các câu trả lời đúng vẫn hoàn toàn tốt cho trường hợp này, tôi muốn chỉ ra rằng so sánh hiệu suất được thực hiện trong câu trả lời của Wolf chỉ để tạo ra các chỉ số. Vì vậy, tôi đã thực hiện điểm chuẩn tương tự để duyệt qua danh sách hiện có theo thứ tự đảo ngược.

TL; DR a[::-1] là nhanh nhất.

Điều kiện tiên quyết:

a = list(range(10))

Câu trả lời của Jason :

%timeit [a[9-i] for i in range(10)]
1.27 µs ± 61.5 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

câu trả lời của martineau :

%timeit a[::-1]
135 ns ± 4.07 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)

Câu trả lời của Michał Šrajer's :

%timeit list(reversed(a))
374 ns ± 9.87 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

câu trả lời của Bene :

%timeit [a[i] for i in range(9, -1, -1)]
1.09 µs ± 11.1 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

Như bạn thấy, trong trường hợp này, không cần phải tạo các chỉ mục một cách rõ ràng, vì vậy phương pháp nhanh nhất là phương pháp tạo ra ít hành động bổ sung.

NB: Tôi đã thử nghiệm trong JupyterLab có "lệnh ma thuật" tiện dụng %timeit. Nó sử dụng tiêu chuẩn timeit.timeitdưới mui xe. Đã kiểm tra Python 3.7.3

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.