วิธีใดเป็นวิธีที่ดีที่สุดในการตรวจสอบว่ามีการส่งผ่านตัวแปรสำหรับสคริปต์หรือไม่:
try:
sys.argv[1]
except NameError:
startingpoint = 'blah'
else:
startingpoint = sys.argv[1]
วิธีใดเป็นวิธีที่ดีที่สุดในการตรวจสอบว่ามีการส่งผ่านตัวแปรสำหรับสคริปต์หรือไม่:
try:
sys.argv[1]
except NameError:
startingpoint = 'blah'
else:
startingpoint = sys.argv[1]
คำตอบ:
ในท้ายที่สุดความแตกต่างระหว่างtry, exceptและการทดสอบlen(sys.argv)ไม่ได้มีนัยสำคัญทั้งหมด ทั้งคู่ค่อนข้างแฮ็คเมื่อเทียบกับargparse.
สิ่งนี้เกิดขึ้นกับฉัน - เป็นอาร์กิวเมนต์งบประมาณต่ำ:
arg_names = ['command', 'x', 'y', 'operation', 'option']
args = dict(zip(arg_names, sys.argv))
คุณยังสามารถใช้เพื่อสร้าง a namedtupleด้วยค่าที่เป็นค่าเริ่มต้นNone- ทั้งหมดในสี่บรรทัด!
Arg_list = collections.namedtuple('Arg_list', arg_names)
args = Arg_list(*(args.get(arg, None) for arg in arg_names))
ในกรณีที่คุณไม่คุ้นเคยnamedtupleมันเป็นเพียงทูเพิลที่ทำหน้าที่เหมือนวัตถุทำให้คุณสามารถเข้าถึงค่าโดยใช้tup.attributeไวยากรณ์แทนtup[0]ไวยากรณ์
ดังนั้นบรรทัดแรกจึงสร้างnamedtupleชนิดใหม่โดยมีค่าสำหรับแต่ละค่าในarg_names. บรรทัดที่สองส่งผ่านค่าจากargsพจนานุกรมโดยใช้getเพื่อส่งคืนค่าเริ่มต้นเมื่อชื่ออาร์กิวเมนต์ที่ระบุไม่มีค่าที่เกี่ยวข้องในพจนานุกรม
ตรวจสอบความยาวของsys.argv:
if len(sys.argv) > 1:
blah = sys.argv[1]
else:
blah = 'blah'
บางคนชอบวิธีการยกเว้นตามที่คุณแนะนำ (เช่นtry: blah = sys.argv[1]; except IndexError: blah = 'blah') แต่ฉันไม่ชอบมันมากนักเพราะมันไม่ได้ "ปรับขนาด" ได้ดีเท่า (เช่นเมื่อคุณต้องการยอมรับสองหรือสามข้อโต้แย้ง) และมันอาจจะซ่อนข้อผิดพลาด (เช่นหากคุณใช้blah = foo(sys.argv[1])แต่foo(...)ยกIndexErrorที่IndexErrorจะได้รับการละเว้น)
try, exceptตราบใดที่คุณกำลังเป็นอะตอมเกี่ยวกับเรื่องนี้ว่ามีอะไรต้องกังวลเกี่ยวกับการเป็น เพียงแค่รอการfooโต้แย้งของคุณจนถึงelseประโยค
argparseนอกจากนี้เมื่อคุณความคิดเกี่ยวกับการปรับกำลังก็ถึงเวลาที่จะย้ายไปยัง
argparse.pyในโครงการบรรทัดคำสั่งทั้งหมดของฉัน
tryประโยค ... ดังนั้นเนื่องจากว่ามันไม่ยาก (และ IMO สวยกว่าเล็กน้อย) ฉันชอบที่จะตรวจสอบความยาวเท่านั้น (นอกจากนี้คุณหลีกเลี่ยงการมีคน ตะโกนใส่คุณที่ใช้ข้อยกเว้นสำหรับการควบคุมการไหล)
tryขอโทษฉันต้องยอมรับ ฉันแค่รู้สึกว่าบางครั้งมันแสดงเจตนาของฉันชัดเจนกว่าifคำพูด
อีกวิธีหนึ่งที่ฉันยังไม่เห็นในรายการคือการตั้งค่า Sentinel ของคุณล่วงหน้า วิธีนี้ใช้ประโยชน์จากการประเมินแบบขี้เกียจของ Python ซึ่งคุณไม่จำเป็นต้องระบุelseคำสั่งเสมอไป ตัวอย่าง:
startingpoint = 'blah'
if len(sys.argv) >= 2:
startingpoint = sys.argv[1]
หรือถ้าคุณกำลังใช้ Syntax CRAZY คุณสามารถใช้ตัวดำเนินการ ternaryของ Python :
startingpoint = sys.argv[1] if len(sys.argv) >= 2 else 'blah'
ฉันใช้สิ่งนี้ - มันไม่เคยล้มเหลว:
startingpoint = 'blah'
if sys.argv[1:]:
startingpoint = sys.argv[1]
startingpointตัวแปรออกจากตัวอย่างได้ แต่คำถามคือการกำหนดตัวแปรทางเลือกดังนั้นฉันจึงทำแบบเดียวกัน
sys.argv[1:]:ว่าหาก สิ่งนี้ใช้ได้กับอาร์กิวเมนต์ตำแหน่งในขณะที่ไม่นับ
มันเป็นรายการ Python ธรรมดา ข้อยกเว้นที่คุณจะจับได้คือ IndexError แต่คุณควรตรวจสอบความยาวแทน
if len(sys.argv) >= 2:
startingpoint = sys.argv[1]
else:
startingpoint = 'blah'
โซลูชันที่ทำงานร่วมกับ fonction ในตัวแผนที่!
arg_names = ['command' ,'operation', 'parameter']
args = map(None, arg_names, sys.argv)
args = {k:v for (k,v) in args}
จากนั้นคุณต้องเรียกพารามิเตอร์ของคุณดังนี้:
if args['operation'] == "division":
if not args['parameter']:
...
if args['parameter'] == "euclidian":
...
คุณสามารถต่อท้ายค่าของ argv [1] กับ argv แล้วตรวจสอบว่า argv [1] ไม่เท่ากับสตริงที่คุณป้อนเข้าไปหรือไม่ตัวอย่าง:
from sys import argv
argv.append('SomeString')
if argv[1]!="SomeString":
print(argv[1])
ค่อนข้างใกล้เคียงกับสิ่งที่ผู้ริเริ่มพยายามทำ นี่คือฟังก์ชั่นที่ฉันใช้:
def get_arg(index):
try:
sys.argv[index]
except IndexError:
return ''
else:
return sys.argv[index]
ดังนั้นการใช้งานจะเป็นดังนี้:
if __name__ == "__main__":
banner(get_arg(1),get_arg(2))