Python 3 เปลี่ยนช่วงเป็นรายการ


178

ฉันพยายามทำรายการด้วยตัวเลข1-1000ในนั้น เห็นได้ชัดว่ามันน่ารำคาญที่จะเขียน / อ่านดังนั้นฉันพยายามทำรายการด้วยช่วงที่อยู่ในนั้น ใน Python 2 ดูเหมือนว่า:

some_list = range(1,1000)

จะใช้งานได้ แต่ใน Python 3 ช่วงจะคล้ายกับxrangeของ Python 2 หรือไม่

ใครสามารถให้ข้อมูลเชิงลึกเกี่ยวกับเรื่องนี้?


1
ด้วยsome_list[i] == i+1ดังนั้นคุณอาจไม่ต้องการรายการจริงๆ
njzk2

1
@RikPoggi ตัวอย่างเช่นหนึ่งอาจต้องจัดหารายการสำหรับฟังก์ชั่นการลงจุด บางครั้งช่วงจะพอเพียง แต่ช่วงไม่สามารถต่อกันได้ (ไม่เปลี่ยนรูป) ดังนั้นถ้าคุณต้องการเพิ่มค่าเริ่มต้นเริ่มต้นให้กับทุกรายการที่ถูกพล็อตนั่นจะต้องเปลี่ยนเป็นรายการด้วย
SherylHohman

คำตอบ:


223

คุณสามารถสร้างรายการจากวัตถุช่วง:

my_list = list(range(1, 1001))

นี่คือวิธีที่คุณทำกับเครื่องกำเนิดไฟฟ้าใน python2.x เช่นกัน โดยทั่วไปแล้วคุณอาจไม่ต้องการรายการเพราะคุณสามารถหาค่าได้my_list[i]อย่างมีประสิทธิภาพมากขึ้น ( i + 1) และหากคุณต้องทำซ้ำมากกว่านั้นคุณก็สามารถถอยกลับไปrangeได้

นอกจากนี้ยังทราบว่าในวันที่ python2.x, xrangeยังคงจัดทำดัชนี1 ซึ่งหมายความว่าrangeใน python3.x ก็มีคุณสมบัติเดียวกัน2

1print xrange(30)[12]ทำงานกับ python2.x

2คำสั่งแบบอะนาล็อกเป็น1ใน python3.x คือprint(range(30)[12])และทำงานได้เช่นกัน


4
นี่เป็นวิธีไปอย่างแน่นอน แต่เป็นไม้
จิ้มฟัน

@jterrace เปลี่ยน "cast" เป็น "convert" คุณพูดถูกมันไม่ใช่นักแสดง ... ฉันไม่รู้จริงๆว่าจะเรียกมันว่าอะไรกันแน่
mgilson

2
ฉันจะพูดว่า "สร้าง" หรือ "สร้าง" (หรืออาจเป็น "รูปธรรม") - ในขณะที่คุณไม่ได้ "แปลง" (เช่น) เครื่องกำเนิดไฟฟ้าไปยังรายการคุณกำลังสร้างวัตถุรายการใหม่จากแหล่งข้อมูลที่เกิดขึ้น ที่จะเป็นผู้สร้าง ... (แต่เพียงแค่แยกผมและไม่แน่ใจ 100% ว่าสิ่งที่ฉันชอบอยู่แล้ว)
Jon Clements

2
+1 ของฉันสำหรับ "สร้าง" เนื่องจากสอดคล้องกับภาษา OO อื่น ๆ list(arg)เป็นที่เข้าใจในภาษาอื่น ๆ เช่นการเรียกสร้างของที่listชั้น จริงๆแล้วมันเป็นกรณีงูหลาม การโต้วาทีไม่ว่าจะเป็นวัตถุที่เต็มไปด้วยในระหว่างการก่อสร้าง (เช่นในกรณี C + +) หรือเฉพาะในช่วงแรกที่เรียกว่าวิธีการโดยอัตโนมัติ (ใน__init__()วิธีการPython ) ไม่สามารถเปลี่ยนความคิดนามธรรมพื้นฐาน มุมมองของฉันอยู่ที่ตัวสร้างรายชื่อใช้เวลา iterator และเติมรายการที่มีค่าที่ส่งกลับ
pepr

2
ทำไมมันถึงมีข้อผิดพลาดในโน๊ตบุ๊ค jupyter และทำงานได้ดีในเชลล์? ข้อผิดพลาด:'range' object is not callable
subtleseeker

34

ใน Pythons <= 3.4 คุณสามารถทำได้ตามที่คนอื่นแนะนำใช้list(range(10))เพื่อสร้างรายการนอกช่วง (โดยทั่วไปสามารถทำซ้ำได้)

อีกทางเลือกหนึ่งที่นำเสนอใน Python 3.5พร้อมด้วยการแกะตัวอย่างโดยใช้*ในรายการตามตัวอักษร[]:

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

แม้ว่านี่จะเทียบเท่ากับlist(r)มันเป็นไวยากรณ์ที่แท้จริงและความจริงที่ว่าไม่มีการเรียกใช้ฟังก์ชั่นที่เกี่ยวข้องจะทำให้มันทำงานได้เร็วขึ้น มันเป็นตัวละครน้อยถ้าคุณจำเป็นต้องเขียนรหัสกอล์ฟ :-)


4
ต้องมีความชัดเจนคุณยังสามารถหนึ่งบรรทัดมัน[*range(10)]ทำงานได้ดีสำหรับเมื่อคุณไม่จำเป็นต้องใช้rangeเพื่อวัตถุประสงค์ใด ๆ listแต่การเริ่มต้น หมายเหตุด้านข้าง: ส่วนที่ชื่นชอบ (ไม่เป็นไร) ของการแยกภาพรวมคือsetตอนนี้ที่ว่างเปล่ามีไวยากรณ์ที่แท้จริง{*()}หรืออย่างที่ฉันเรียกมันว่าโอเปอเรเตอร์ลิงตาเดียว ;-)
ShadowRanger

@ShadowRanger นั่นเป็นสิ่งที่ฉันคิดตอนแรกเกี่ยวกับการเขียนมัน ฉันตัดสินใจที่จะ verbose อีกเล็กน้อยเพื่อไม่ให้สับสนกับผู้ใช้ Python ใหม่ :-)
Dimitris Fasarakis Hilliard

26

ใน Python 3.x range()ฟังก์ชั่นมีประเภทของตัวเอง ดังนั้นในกรณีนี้คุณต้องใช้ตัววนซ้ำ

list(range(1000))


11
"ในกรณีนี้คุณต้องใช้ตัววนซ้ำ"? สิ่งที่ควรจะหมายถึงห่า?
user2357112 รองรับ Monica

2
ฉันใช้ python 3.7 และพยายาม x = list (ช่วง (1000)) แต่ได้รับข้อผิดพลาด TypeError: วัตถุ 'list' ไม่สามารถเรียกได้
Earthshaker

@Earthshaker คุณต้องพิมพ์ผิดเช่นlist(range(1000))()
wjandrea

17

เหตุผลที่ Python3 ขาดฟังก์ชั่นสำหรับการรับรายการที่มีลำดับโดยตรงนั้นเป็นเพราะผู้ออกแบบ Python3 ดั้งเดิมนั้นค่อนข้างเป็นมือใหม่ใน Python2 เขาพิจารณาการใช้range()ฟังก์ชั่นในวง for เท่านั้นดังนั้นรายการไม่ควรถูกขยาย ในความเป็นจริงบ่อยครั้งที่เราจำเป็นต้องใช้range()ฟังก์ชั่นเพื่อสร้างรายการและส่งผ่านเข้าไปในฟังก์ชั่น

ดังนั้นในกรณีนี้ Python3 จึงสะดวกกว่าเมื่อเปรียบเทียบกับ Python2 เนื่องจาก:

  • ใน Python2 เรามีxrange()และrange();
  • ใน Python3 เรามีrange()และlist(range())

อย่างไรก็ตามคุณยังสามารถใช้การขยายรายการได้ด้วยวิธีนี้:

[*range(N)]

3
ประเด็นทั้งหมดคือการทำให้สะดวกต่อการทำ a listเพราะมันมักจะเป็นสิ่งที่ผิด สำหรับ 99 จาก 100 กรณีการใช้งานทำให้เกิดขึ้นจริงlistจะไม่มีประสิทธิภาพและไม่มีจุดหมายตั้งแต่rangeตัวเองทำหน้าที่เหมือนลำดับไม่เปลี่ยนรูปในเกือบทุกวิถีทางบางครั้งได้อย่างมีประสิทธิภาพมากขึ้นในการบูต (เช่นการบรรจุการทดสอบสำหรับints มีO(1)เทียบกับO(n)สำหรับlists) ใน Python 2 ผู้คนมักจะใช้เป็นrangeค่าเริ่มต้นแม้ว่าจะxrangeเป็นตัวเลือกที่ดีกว่า ใน Python 3 คุณสามารถเลือกที่จะlistไม่รับโดยไม่ตั้งใจโดยใช้ชื่อที่ไม่ถูกต้อง
ShadowRanger

7
ความคิดเห็นเกี่ยวกับนักออกแบบ Python 3 และความเชี่ยวชาญของเขาใน Python 2 ค่อนข้างกล้าหาญและไม่ตรงประเด็น
kazarey

@kazarey แต่มันเป็นเรื่องจริงเหรอ? งูหลามมีหลายสิ่งหลายอย่างที่น่าสงสัยตามสายเหล่านี้
javadba

1
จะอัปโหลดโดยเฉพาะอย่างยิ่งสำหรับการเปิดออกแบบย่อเพื่อสร้างรายการ แต่ฉันเห็นด้วยกับ @ kazarey ความคิดเห็นเกี่ยวกับนักออกแบบนั้นมีทั้งที่ไม่มีมูลความจริง
Nubarke

12

คุณไม่จำเป็นต้องใช้ตัวเลข 1-1000 ในรายการ แต่ถ้าด้วยเหตุผลบางอย่างคุณจำเป็นต้องใช้ตัวเลขเหล่านี้จริงๆแล้วคุณสามารถทำได้:

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

รายการความเข้าใจสั้น ๆ :

ความเข้าใจในรายการด้านบนแปลเป็น:

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

นี่เป็นเพียงไวยากรณ์รายการความเข้าใจ แต่จาก 2.x ฉันรู้ว่าสิ่งนี้จะทำงานใน python 3 แต่ฉันไม่แน่ใจว่ามีไวยากรณ์ที่อัปเกรดเช่นกันหรือไม่

ช่วงเริ่มต้นรวมพารามิเตอร์แรก แต่สิ้นสุดถึงไม่รวมพารามิเตอร์ตัวที่สอง (เมื่อระบุพารามิเตอร์ 2 ตัวหากพารามิเตอร์ตัวแรกถูกปล่อยออกไปมันจะเริ่มต้นที่ '0')

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

20
ทำไมต้องเข้าใจ? เพียงแค่:list(range(1000))
Rik Poggi

ขอบคุณ! คุณจะอธิบายไหมว่าทำไมมันถึงเป็นเพื่อฉันใน ... แทนที่จะทำเพื่อฉันด้วย
โบ้ทเฮาส์

ฉันไม่ได้ทำงานกับ python3 ดังนั้นฉันจึงไม่แน่ใจเกี่ยวกับวิธีการใช้งาน ฉันรู้ว่าความเข้าใจจะได้ผล แต่ไม่ได้ 100% กับการคัดเลือกนักแสดง แต่ถ้าการคัดเลือกนักแสดงใช้งานได้แสดงว่าคุณพูดถูกแล้ว
inspectorG4dget

1
@ inspectorG4dget: มันไม่ได้ "หล่อ" ก็เรียกlist()constructor กับ iterable ตัวlist()สร้างรู้วิธีการสร้างรายการใหม่เมื่อได้รับวัตถุ iterable ใด ๆ
Greg Hewgill

4
@ inspectorG4dget: list(range(1000))จะทำงานใน python3 เหมือนlist(xrange(1000))ใน python2
Rik Poggi

4

ที่จริงแล้วถ้าคุณต้องการ 1-1000 (รวม) ให้ใช้range(...)ฟังก์ชั่นที่มีพารามิเตอร์ 1 และ 1001: range(1, 1001)เนื่องจากrange(start, end)ฟังก์ชั่นจะเริ่มตั้งแต่ต้นจนจบ (end-1)


0

ใช้พิสัยใน Python 3

นี่คือตัวอย่างฟังก์ชั่นที่ส่งกลับระหว่างตัวเลขจากสองตัวเลข

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

ผลลัพธ์

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

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

ดูเหมือนว่าจะตอบคำถามอื่น ...
wjandrea

-1

อันที่จริงนี่คือการไล่ระดับย้อนยุคของ Python3 เมื่อเทียบกับ Python2 แน่นอนว่า Python2 ที่ใช้ range () และ xrange () สะดวกกว่า Python3 ซึ่งใช้ list (range ()) และ range () ตามลำดับ เหตุผลก็เพราะว่าผู้ออกแบบดั้งเดิมของ Python3 นั้นไม่ค่อยมีประสบการณ์มากนักพวกเขาพิจารณาเฉพาะการใช้ฟังก์ชั่นพิสัยโดยผู้เริ่มต้นใช้งานหลายคนเพื่อย้ำผ่านองค์ประกอบจำนวนมากที่ทั้งหน่วยความจำและ CPU ไม่มีประสิทธิภาพ แต่พวกเขาไม่สนใจการใช้ฟังก์ชัน range เพื่อสร้างรายการตัวเลข ตอนนี้มันสายเกินไปแล้วที่พวกเขาจะเปลี่ยนกลับมาแล้ว

ถ้าฉันจะเป็นนักออกแบบของ Python3 ฉันจะ:

  1. ใช้ irange เพื่อส่งคืนตัววนซ้ำลำดับ
  2. ใช้ lrange เพื่อส่งคืนรายการลำดับ
  3. ใช้ range เพื่อส่งคืนตัววนซ้ำลำดับ (ถ้าจำนวนขององค์ประกอบมีขนาดใหญ่เช่นช่วง (9999999) หรือรายการลำดับ (หากจำนวนองค์ประกอบมีขนาดเล็กเช่นช่วง (10))

นั่นควรจะเหมาะสมที่สุด


คำถามนี้จะตอบคำถามได้อย่างไร
wjandrea

ใช่มันตอบคำถามโดยขอให้นักพัฒนา Python3 เปลี่ยนและปรับปรุง Python3 แต่ไม่น่าเป็นไปได้ที่พวกเขาจะเปลี่ยนแปลงเนื่องจากไม่สง่างาม
xuancong84
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.