เป็นไปได้หรือไม่ที่จะประกาศตัวแปรโดยไม่ต้องกำหนดค่าใด ๆ ใน Python?


288

เป็นไปได้ไหมที่จะประกาศตัวแปรใน Python เช่น:

var

เพื่อที่จะเริ่มต้นเป็นไม่มี ดูเหมือนว่า Python จะอนุญาตสิ่งนี้ แต่ทันทีที่คุณเข้าถึงมันจะเกิดปัญหา เป็นไปได้ไหม ถ้าไม่ทำไม

แก้ไข: ฉันต้องการทำสิ่งนี้สำหรับกรณีเช่นนี้:

value

for index in sequence:

   if value == None and conditionMet:
       value = index
       break

ซ้ำ

ที่เกี่ยวข้อง


1
สามารถโพสต์โปรแกรมขนาดเล็กที่เป็นสาเหตุของปัญหานี้ได้
Preet Sangha

คุณได้โพสต์คำถามที่ซ้ำกันโหวตให้ปิดคำถามนี้เพื่ออีกคำถามหนึ่ง
Jerub

ยังมีข้อแตกต่างอยู่บ้างอันนี้เกี่ยวข้องกับการไม่สามารถใช้ตัวแปรเพียงแค่ประกาศ
Joan Venge

ไม่มีสิ่งใดที่เหมือนกับการประกาศตัวแปรในโลกหลามเนื่องจากคำถามแรกของคุณอธิบาย
ฮาร์เลย์ Holcombe

1
ทำไมไม่มีใครเคยพูดว่า 'แค่มอบหมายให้มัน' เพราะตัวแปรไม่มีอยู่ก่อนที่พวกเขาจะถูกกำหนดให้เป็นประจำเดือน และตัวแปรในไพ ธ อนไม่ได้มีข้อมูลประเภท วัตถุทำเช่นนั้น ตัวแปรเป็นเพียงการถือวัตถุ ณ เวลานั้น นอกจากนี้โปรแกรมข้างต้นควรโยนข้อยกเว้น NameError ในบรรทัดแรก (นั่นคือสิ่งที่ฉันได้ใน 2.X และ 3.X ทั้งคู่)
osirisgothra

คำตอบ:


359

ทำไมไม่ทำเช่นนี้:

var = None

Python เป็นแบบไดนามิกดังนั้นคุณไม่จำเป็นต้องประกาศสิ่งต่างๆ จะมีอยู่โดยอัตโนมัติในขอบเขตแรกที่ได้รับมอบหมาย ดังนั้นสิ่งที่คุณต้องมีก็คือคำสั่งมอบหมายปกติแบบเก่าดังกล่าวข้างต้น

นี่เป็นสิ่งที่ดีเพราะคุณจะไม่มีวันจบลงด้วยตัวแปรที่ไม่มีการกำหนดค่าเริ่มต้น แต่ระวัง - นี่ไม่ได้หมายความว่าคุณจะไม่จบลงด้วยตัวแปรที่เริ่มต้นอย่างไม่ถูกต้อง หากคุณเริ่มต้นสิ่งที่ต้องNoneทำให้แน่ใจว่านั่นคือสิ่งที่คุณต้องการและกำหนดสิ่งที่มีความหมายมากขึ้น


1
ฉันจะทำอย่างนั้น แต่แค่คิดโดยปริยายว่ามันจะทำอย่างนั้น
Joan Venge

7
ประเด็นคือเพื่อให้ชัดเจนไม่ได้บอกเป็นนัย ไม่ต้องเดาว่าค่าเริ่มต้นคืออะไร ไม่สงสัยเลยว่าตัวแปรที่ไม่มีการกำหนดเริ่มต้นนั้นมีข้อยกเว้นหรือมีค่าที่มีประโยชน์อย่างน่าอัศจรรย์
S.Lott

2
ปัญหาเดียวที่ฉันมีกับสิ่งนี้คือฉันกำลังติดตามตัวนับ (minValue) และทุกครั้งที่ค่าต่ำกว่านั้นฉันก็กำหนดให้เป็น minValue ใหม่ ถ้าฉันประกาศ minValue เป็น None แต่ก็เห็นได้ชัดว่ามันยังคงต่ำกว่าตัวเลขใด ๆ ที่ฉันเปรียบเทียบกับ ฉันลงเอยด้วยการเริ่มต้นที่ sys.maxint
TJ Biddle

... มันจะอยู่ในขอบเขตแรกโดยอัตโนมัติ ดังนั้นคุณต้องตามล่าการมอบหมายครั้งแรกและคิดออก ฮึ!
Ed Randall

56

ฉันอยากแนะนำให้คุณอ่านภาษาอื่น ๆ มี "ตัวแปร" (ฉันเพิ่มมันเป็นลิงค์ที่เกี่ยวข้อง) - ภายในสองนาทีคุณจะรู้ว่า Python มี "ชื่อ" ไม่ใช่ "ตัวแปร"

val = None
# ...
if val is None:
   val = any_object

คุณสามารถเขียนval = val or any_objectเพื่อเริ่มต้นมัน
Zoltán

1
@ Zoltán: มันจะแตกถ้าค่าที่ถูกต้องสำหรับ val คือ "false" เช่นศูนย์หรือว่างเปล่า ใช้isสำหรับทดสอบว่ามีค่าNoneหรือไม่
jfs

หลังจากอ่านบทความที่ลิงก์ที่ให้มาดูเหมือนจะน้อยกว่าความซับซ้อนทางความหมาย
Andrew P.

29

ใน Python 3.6+ คุณสามารถใช้คำอธิบายประกอบตัวแปรสำหรับสิ่งนี้:

https://www.python.org/dev/peps/pep-0526/#abstract

PEP 484 แนะนำประเภทคำแนะนำ, คำอธิบายประกอบประเภท aka ในขณะที่จุดสนใจหลักคือคำอธิบายประกอบฟังก์ชั่นมันยังแนะนำแนวคิดของประเภทความคิดเห็นเพื่ออธิบายตัวแปร:

# 'captain' is a string (Note: initial value is a problem)
captain = ...  # type: str

PEP 526 มีจุดมุ่งหมายที่การเพิ่มไวยากรณ์ให้กับ Python เพื่อใส่คำอธิบายประกอบประเภทของตัวแปร (รวมถึงตัวแปรคลาสและตัวแปรอินสแตนซ์) แทนที่จะแสดงความคิดเห็นผ่านข้อคิดเห็น:

captain: str  # Note: no initial value!

ดูเหมือนว่าจะตรงกับสิ่งที่คุณถามมากขึ้น "เป็นไปได้หรือไม่ที่จะประกาศตัวแปรโดยไม่ต้องกำหนดค่าใด ๆ ใน Python?"


2
คำตอบที่ยอดเยี่ยม
Ben

16

ฉันไม่แน่ใจว่าคุณกำลังพยายามทำอะไร Python เป็นภาษาแบบไดนามิกมาก โดยปกติคุณไม่จำเป็นต้องประกาศตัวแปรจนกว่าคุณจะกำหนดหรือใช้งานจริง ฉันคิดว่าสิ่งที่คุณต้องการจะทำก็แค่

foo = None

ซึ่งจะกำหนดค่าให้กับตัวแปรNonefoo

แก้ไข: สิ่งที่คุณจริงๆดูเหมือนจะต้องการจะทำคือเพียงแค่นี้:

#note how I don't do *anything* with value here
#we can just start using it right inside the loop

for index in sequence:
   if conditionMet:
       value = index
       break

try:
    doSomething(value)
except NameError:
    print "Didn't find anything"

เป็นการยากที่จะบอกว่าเป็นสไตล์ที่ถูกต้องในการใช้งานจากตัวอย่างรหัสย่อ ๆ หรือไม่ แต่เป็นวิธีการทำงานแบบ "Pythonic" ที่มากขึ้น

แก้ไข: ด้านล่างเป็นความเห็นโดย JFS (โพสต์ที่นี่เพื่อแสดงรหัส)

ไม่เกี่ยวข้องกับคำถามของ OP แต่สามารถเขียนรหัสข้างต้นใหม่เป็น:

for item in sequence:
    if some_condition(item): 
       found = True
       break
else: # no break or len(sequence) == 0
    found = False

if found:
   do_something(item)

หมายเหตุ: หากsome_condition()เพิ่มข้อยกเว้นfoundจะถูกยกเลิก
หมายเหตุ: หาก len (sequence) == 0 itemจะถูก unbound

รหัสข้างต้นไม่แนะนำให้เลือก วัตถุประสงค์คือเพื่อแสดงให้เห็นว่าตัวแปรโลคอลทำงานอย่างไรกล่าวคือสามารถกำหนด "ตัวแปร" คือ "กำหนด" ได้เฉพาะที่รันไทม์ในกรณีนี้ วิธีที่ดีกว่า:

for item in sequence:
    if some_condition(item):
       do_something(item)
       break

หรือ

found = False
for item in sequence:
    if some_condition(item):
       found = True
       break

if found:
   do_something(item)

มีความแตกต่างระหว่างภาษาแบบไดนามิกและภาษาแบบไดนามิกมากหรือไม่
Gavin Miller

มีบทความที่ดีที่อธิบายถึงแกนต่าง ๆ ของการพิมพ์ภาษาโปรแกรมและวิธีการต่อเนื่องไม่ใช่ค่าบูลีน โชคไม่ดีที่ฉันไม่สามารถหาบทความนั้นได้อีกเมื่อฉันต้องการอ้างถึง: (ฉันถือว่า Python "มีความเคลื่อนไหว" เพราะมันอยู่ไกลสุดในหลายแกน
kquinn

3

ฉันมักจะเริ่มต้นตัวแปรเป็นสิ่งที่แสดงถึงประเภทเช่น

var = ""

หรือ

var = 0

ถ้ามันจะเป็นวัตถุก็อย่าเริ่มต้นมันจนกว่าคุณจะยกตัวอย่าง:

var = Var()

3

ถ้าคุณต้องการตรวจสอบว่ามีการกำหนดตัวแปรหรือไม่ทำไมไม่ลองตรวจสอบว่าอยู่ในแถว () หรือ globals () หรือไม่ รหัสของคุณเขียนใหม่:

for index in sequence:
   if 'value' not in globals() and conditionMet:
       value = index
       break

หากเป็นตัวแปรท้องถิ่นที่คุณต้องการให้แทนที่ globals () ด้วย locals ()


2

ก่อนอื่นเลยการตอบคำถามที่คุณเคยถาม

ถาม: ฉันจะค้นพบได้อย่างไรว่าตัวแปรถูกกำหนดไว้ที่จุดหนึ่งในรหัสของฉันหรือไม่

ตอบ: อ่านในไฟล์ต้นฉบับจนกว่าคุณจะเห็นบรรทัดที่มีการกำหนดตัวแปรนั้น

แต่ยิ่งไปกว่านั้นคุณได้รับตัวอย่างรหัสว่ามีพีชคณิตต่าง ๆ ที่ค่อนข้างไพเราะ คุณกำลังหาวิธีสแกนลำดับขององค์ประกอบที่ตรงกับเงื่อนไขดังนั้นนี่คือวิธีแก้ไข:

def findFirstMatch(sequence):
    for value in sequence:
        if matchCondition(value):
            return value

    raise LookupError("Could not find match in sequence")

ชัดเจนในตัวอย่างนี้คุณสามารถแทนที่raiseด้วยreturn Noneขึ้นอยู่กับสิ่งที่คุณต้องการบรรลุ

หากคุณต้องการทุกสิ่งที่ตรงกับเงื่อนไขที่คุณสามารถทำได้:

def findAllMatches(sequence):
    matches = []
    for value in sequence:
        if matchCondition(value):
            matches.append(value)

    return matches

มีอีกวิธีหนึ่งในการทำเช่นนี้โดยyieldที่ฉันจะไม่รำคาญที่จะแสดงให้คุณเห็นเพราะมันค่อนข้างซับซ้อนในวิธีที่มันใช้งานได้

นอกจากนี้ยังมีวิธีหนึ่งในการบรรลุเป้าหมายนี้:

all_matches = [value for value in sequence if matchCondition(value)]

2

หากฉันเข้าใจตัวอย่างของคุณถูกต้องคุณไม่จำเป็นต้องอ้างถึง 'คุณค่า' ในคำสั่ง if คุณกำลังแตกจากลูปทันทีที่สามารถตั้งค่าเป็นอะไรก็ได้

value = None
for index in sequence:
   doSomethingHere
   if conditionMet:
       value = index
       break 

1

ดูเหมือนว่าคุณกำลังพยายามเขียน C ใน Python หากคุณต้องการหาบางอย่างในลำดับไพ ธ อนมีฟังก์ชันในตัวเพื่อทำสิ่งนั้นเช่น

value = sequence.index(blarg)

1

มันเป็นคำถามที่ดีและน่าเสียดายที่คำตอบที่var = Noneได้รับมอบหมายอยู่แล้วและถ้าสคริปต์ของคุณทำงานหลายครั้งมันจะถูกเขียนทับNoneทุกครั้ง

มันไม่เหมือนกับการกำหนดโดยไม่มีการมอบหมาย ฉันยังคงพยายามหาวิธีหลีกเลี่ยงปัญหานี้


1

เป็นไปได้ไหมที่จะประกาศตัวแปรใน Python (var = None):

def decl_var(var=None):
if var is None:
    var = []
var.append(1)
return var

0
var_str = str()
var_int = int()

แก่นแก้วแก่นแก้ว! ตัวแปรไม่ได้เชื่อมโยงประเภทวัตถุจะทำ var_str ไม่ควรถูก จำกัด ด้วยชื่อสามัญดังกล่าว หากคุณกำลังจะทำสิ่งนี้ให้ความหมายเช่น 'var_age' หรือ 'var_name' ค่าดังกล่าวสามารถนำมาเป็นจำนวนเต็มหรือสตริงหรือสิ่งที่คุณต้องการและเปลี่ยนเป็นวัตถุวิญญาณของสิ่งที่ทำให้หลามแตกต่างจากภาษาอื่น ๆ พวกเขาบอกว่าถ้าคุณพบว่าตัวเองต้องการทำเช่นนี้ตลอดเวลาคุณอาจต้องการใช้ภาษาอื่น
osirisgothra

0

หากNoneเป็นค่าข้อมูลที่ถูกต้องแล้วคุณต้องตัวแปรอีกวิธีหนึ่ง คุณสามารถใช้:

var = object()

ยามนี้จะแนะนำโดยนิค Coghlan


0

คุณสามารถหลอกล่ามด้วยผู้แปลที่น่าเกลียดif None: var = None มันไม่ทำอะไรเลยนอกจากการเพิ่มตัวแปรvarลงในพจนานุกรมตัวแปรท้องถิ่นโดยไม่ต้องเริ่มต้นมัน ล่ามจะโยนข้อยกเว้น UnboundLocalError หากคุณพยายามใช้ตัวแปรนี้ในฟังก์ชั่นหลังจากนั้น สิ่งนี้จะใช้ได้กับงูหลามรุ่นโบราณเช่นกัน ไม่ง่ายหรือสวยงาม แต่อย่าหวังมากจากงูหลาม

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