Python 3 biến phạm vi thành một danh sách


178

Tôi đang cố gắng tạo một danh sách với các số 1-1000trong đó. Rõ ràng điều này sẽ gây khó chịu khi viết / đọc, vì vậy tôi đang cố gắng tạo một danh sách với một phạm vi trong đó. Trong Python 2 có vẻ như:

some_list = range(1,1000)

sẽ hoạt động, nhưng trong Python 3, phạm vi tương tự như xrangePython 2?

Bất cứ ai có thể cung cấp một số cái nhìn sâu sắc về điều này?


1
Ngoài ra, some_list[i] == i+1vì vậy bạn có thể không thực sự cần một danh sách nào.
njzk2

1
@RikPoggi. ví dụ, người ta có thể cần cung cấp một danh sách cho hàm vẽ. Đôi khi một phạm vi sẽ đủ, nhưng một phạm vi không thể được nối (là bất biến), vì vậy nếu bạn cần thêm một giá trị bắt đầu mặc định cho tất cả các danh sách được vẽ, thì cũng cần phải được chuyển thành một danh sách.
SherylHohman

Câu trả lời:


223

Bạn chỉ có thể xây dựng một danh sách từ đối tượng phạm vi:

my_list = list(range(1, 1001))

Đây là cách bạn làm điều đó với các trình tạo trong python2.x. Nói một cách điển hình, có lẽ bạn không cần một danh sách mặc dù bạn có thể đạt được giá trị my_list[i]hiệu quả hơn ( i + 1) và nếu bạn chỉ cần lặp lại nó, bạn có thể quay lạirange .

Cũng lưu ý rằng trên python2.x, xrangevẫn có thể lập chỉ mục 1 . Điều này có nghĩa là rangetrên python3.x cũng có cùng thuộc tính 2

1print xrange(30)[12] hoạt động cho python2.x

2 Câu lệnh tương tự thành 1 trong python3.x là print(range(30)[12])và nó cũng hoạt động.


4
Đây chắc chắn là con đường để đi, nhưng một nitpick: đây không thực sự là một "diễn viên"
jterrace

@jterrace đã thay đổi "cast" thành "convert". Bạn nói đúng về việc nó không phải là một diễn viên ... Tôi thực sự không biết nên gọi nó chính xác là gì.
mgilson

2
Tôi sẽ nói "xây dựng" hoặc "xây dựng" (hoặc có thể là "vật chất hóa") - vì bạn không "chuyển đổi" (như vậy) một trình tạo thành danh sách, bạn đang tạo một đối tượng danh sách mới từ nguồn dữ liệu xảy ra trở thành một máy phát điện ... (nhưng chỉ là chia tóc và không chắc chắn 100% những gì tôi ủng hộ dù sao)
Jon Clements

2
+1 của tôi cho "xây dựng" vì nó phù hợp với các ngôn ngữ OO khác. Điều list(arg)này được hiểu trong các ngôn ngữ khác như gọi một hàm tạo của listlớp. Thật ra, đó cũng là trường hợp Python. Các cuộc tranh luận về việc liệu đối tượng được lấp đầy trong quá trình xây dựng (như trong trường hợp C ++) hay chỉ trong phương thức được gọi tự động đầu tiên (như trong __init__()phương thức Python ) không thể thay đổi ý tưởng trừu tượng cơ bản. Quan điểm của tôi là hàm tạo danh sách lấy iterator và điền vào danh sách với các giá trị được trả về .
pepr

2
Tại sao nó lại báo lỗi trong máy tính xách tay jupyter và hoạt động tốt trong shell? Lỗi:'range' object is not callable
subleseeker

34

Trong Pythons <= 3,4, bạn có thể, như những người khác đề xuất, sử dụng list(range(10))để tạo danh sách ngoài phạm vi (Nói chung, bất kỳ lần lặp nào).

Một cách khác, được giới thiệu trong Python 3.5với các khái quát giải nén của nó, bằng cách sử dụng *trong một danh sách bằng chữ []:

>>> r = range(10)
>>> l = [*r]
>>> print(l)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

Mặc dù điều này tương đương với list(r), nhưng đó là cú pháp theo nghĩa đen và thực tế là không có lệnh gọi hàm nào tham gia sẽ cho phép nó thực thi nhanh hơn. Nó cũng ít ký tự hơn, nếu bạn cần viết mã golf :-)


4
Để rõ ràng, bạn vẫn có thể một dòng: [*range(10)]hoạt động tốt khi bạn không cần rangecho bất kỳ mục đích nào ngoài việc khởi tạo list. Lưu ý phụ: Phần yêu thích của tôi (được, không thực sự) trong các khái quát về giải nén là setbây giờ các s rỗng có một cú pháp theo nghĩa đen {*()}, hoặc như tôi gọi nó là toán tử khỉ một mắt. ;-)
ShadowRanger

@ShadowRanger đó là cách ban đầu tôi nghĩ về việc viết nó. Tôi quyết định dài dòng hơn một chút để không nhầm lẫn người dùng Python mới :-)
Dimitris Fasarakis Hilliard

26

trong Python 3.x, range()hàm có kiểu riêng của nó. vì vậy trong trường hợp này bạn phải sử dụng iterator

list(range(1000))


11
"trong trường hợp này bạn phải sử dụng iterator"? Cái quái gì có nghĩa là gì?
user2357112 hỗ trợ Monica

2
Tôi đang sử dụng python 3.7 và đã thử x = list (phạm vi (1000)) nhưng gặp lỗi LoạiError: đối tượng 'list' không thể gọi được
Earthshaker

@Earthshaker Bạn phải có một lỗi đánh máy, nhưlist(range(1000))()
wjandrea

17

Lý do tại sao Python3 thiếu một chức năng để trực tiếp nhận được một danh sách có phạm vi là bởi vì trình thiết kế Python3 ban đầu khá mới lạ trong Python2. Ông chỉ xem xét việc sử dụng range()hàm trong một vòng lặp for, do đó, danh sách không bao giờ cần phải được mở rộng. Trong thực tế, chúng ta thường cần sử dụng range()hàm để tạo danh sách và chuyển vào hàm.

Do đó, trong trường hợp này, Python3 kém thuận tiện hơn so với Python2 vì:

  • Trong Python2, chúng ta có xrange()range();
  • Trong Python3, chúng ta có range()list(range())

Tuy nhiên, bạn vẫn có thể sử dụng mở rộng danh sách theo cách này:

[*range(N)]

3
Toàn bộ điểm là làm cho nó kém thuận lợi để thực hiện một list, bởi vì đó là thường là điều sai trái để làm. Đối với 99 trong số 100 trường hợp sử dụng, việc thực listhiện là không hiệu quả và vô nghĩa, vì rangebản thân nó hoạt động như một chuỗi bất biến theo hầu hết mọi cách, đôi khi hiệu quả hơn để khởi động (ví dụ: kiểm tra ngăn chặn đối với ints là O(1), so O(n)với lists). Trong Python 2, mọi người có xu hướng sử dụng rangetheo mặc định, mặc dù xrangehầu như luôn luôn là lựa chọn tốt hơn; trong Python 3, bạn có thể chọn tham gia một cách rõ ràng list, không vô tình nhận được nó bằng cách sử dụng tên sai.
ShadowRanger

7
Nhận xét về người thiết kế Python 3 và chuyên môn của anh ta về Python 2 khá táo bạo và không hoàn hảo.
kazarey

@kazarey Nhưng có thật không? Có rất nhiều điều trong python có thể nghi ngờ dọc theo những dòng này
javadba

1
Sẽ upvote, đặc biệt là cho việc giải nén tốc ký để xây dựng danh sách, nhưng tôi đồng ý với @kazarey. Nhận xét về nhà thiết kế là không có cơ sở (hoặc ít nhất, không được phản hồi bởi các tài liệu tham khảo) và không cần thiết.
Nubarke

12

Bạn thực sự không cần phải sử dụng các số 1-1000 trong danh sách. Nhưng nếu vì lý do nào đó bạn thực sự cần những con số này, thì bạn có thể làm:

[i for i in range(1, 1001)]

Danh sách Hiểu một cách ngắn gọn:

Việc hiểu danh sách trên có nghĩa là:

nums = []
for i in range(1, 1001):
    nums.append(i)

Đây chỉ là cú pháp hiểu danh sách, mặc dù từ 2.x. Tôi biết rằng nó sẽ hoạt động trong python 3, nhưng tôi không chắc có một cú pháp nâng cấp nào không

Phạm vi bắt đầu bao gồm tham số đầu tiên; nhưng kết thúc Lên đến, Không bao gồm Thông số thứ hai (khi được cung cấp 2 tham số; nếu tham số đầu tiên bị tắt, nó sẽ bắt đầu ở '0')

range(start, end+1)
[start, start+1, .., end]

20
Tại sao hiểu? Chỉ cần:list(range(1000))
Rik Poggi

Cảm ơn! Bạn có phiền giải thích lý do tại sao tôi cho tôi vào ... thay vì chỉ đơn giản là cho tôi vào không?
Boathouse

Tôi đã không làm việc với python3. Vì vậy, tôi không hoàn toàn chắc chắn về cách thức hoạt động. Tôi biết việc hiểu sẽ hiệu quả, nhưng không phải là 100% trong buổi casting. Nhưng nếu việc đúc diễn ra hiệu quả, thì bạn đã đúng và cách của bạn là pythonic hơn.
thanh

1
@ InspectorG4dget: Không phải là "truyền", nó gọi hàm list()tạo bằng một lần lặp . Hàm list()tạo biết cách tạo một danh sách mới khi được cung cấp bất kỳ đối tượng lặp nào.
Greg Hewgill

4
@ InspectorG4dget: list(range(1000))sẽ hoạt động trong python3 giống như list(xrange(1000))trong python2
Rik Poggi

4

Trên thực tế, nếu bạn muốn 1-1000 (đã bao gồm), hãy sử dụng range(...)hàm với tham số 1 và 1001 : range(1, 1001), vì range(start, end)hàm này đi từ đầu đến (cuối 1), đã bao gồm.


0

Sử dụng Phạm vi trong Python 3.

Dưới đây là một hàm ví dụ trả về giữa các số từ hai số

def get_between_numbers(a, b):
    """
    This function will return in between numbers from two numbers.
    :param a:
    :param b:
    :return:
    """
    x = []
    if b < a:
        x.extend(range(b, a))
        x.append(a)
    else:
        x.extend(range(a, b))
        x.append(b)

    return x

Kết quả

print(get_between_numbers(5, 9))
print(get_between_numbers(9, 5))

[5, 6, 7, 8, 9]  
[5, 6, 7, 8, 9]

Điều này dường như đang trả lời một câu hỏi khác ...?
wjandrea

-1

Trong thực tế, đây là một sự phân cấp retro của Python3 so với Python2. Chắc chắn, Python2 sử dụng phạm vi () và xrange () thuận tiện hơn Python3 sử dụng danh sách (phạm vi ()) và phạm vi () tương ứng. Lý do là bởi vì người thiết kế ban đầu của Python3 không có nhiều kinh nghiệm, họ chỉ xem xét việc sử dụng chức năng phạm vi bởi nhiều người mới bắt đầu lặp lại một số lượng lớn các yếu tố trong đó cả bộ nhớ và CPU không hiệu quả; nhưng họ đã bỏ qua việc sử dụng hàm phạm vi để tạo danh sách số. Bây giờ, đã quá muộn để họ thay đổi trở lại.

Nếu tôi là người thiết kế Python3, tôi sẽ:

  1. sử dụng irange để trả về một trình vòng lặp trình tự
  2. sử dụng lrange để trả về một danh sách trình tự
  3. sử dụng phạm vi để trả về trình lặp trình tự (nếu số phần tử lớn, ví dụ: phạm vi (9999999) hoặc danh sách trình tự (nếu số phần tử nhỏ, ví dụ: phạm vi (10))

Điều đó nên tối ưu.


Làm thế nào để trả lời câu hỏi này?
wjandrea

Vâng, nó trả lời câu hỏi bằng cách yêu cầu các nhà phát triển Python3 thay đổi và cải thiện Python3. Nhưng không chắc là họ sẽ thay đổi vì họ không thanh lịch.
xuancong84
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.