מה ערך ה index? וכמה איברים יש ברשימה?
כמו שכתבתי ,
יש 8 אברים שאמורים להיכנס לרשימה (בפועל נכנסים רק 7)
האינדקס האחרון (כלומר אינדקס 7 המכיל את המס’ 6-) לא נכנס
התכנית מפסיקה ונזרקת הודעת השגיאה דלעיל
בלי קשר , בעקבות ההערה שלך כתבתי את התכנית הבאה ע"י שימוש ב sys.stdin
import sys
import math
while True:
number = sys.stdin.readline()
if number == "":break
try:
print math.sqrt(float(number))
except ValueError as e:
print "Please enter numbers > 0 only"
print e.message```
רק לא הבנתי למה התנאי הזה לא מתקיים אף פעם
if number == "":break
תרגיל 2 חריגים
import sys
path = r"C:\Python\files_3\\" + sys.argv[1]
try:
with open (path,"r") as readline:
count = [line for line in readline]
print len(count)
except IOError as e:
print "Sorry, the file %s is not exist" %(sys.argv[1])
print e.message
אבל למה זה לא מדפיס את ה e.message
?
הי,
לגבי הרשימה מאמין שתגיע לזה גם לבד. תמשיך לעבוד עם הדפסות ותראה מה בדיוק נכנס לרשימה ולמה.
לגבי התנאי - הוא לא מתקיים כי שורה שקראת מ stdin היא אף פעם לא ריקה. היא תמיד מכילה תו מיוחד שנקרא ״תו ירידת שורה״ שמציין שהשורה הסתיימה וממשיכים לשורה הבאה.
לגבי השאלה האחרונה ב IOError אין שדה message ולכן צריך להדפיס את e עצמו:
import sys
path = r"C:\Python\files_3\\" + sys.argv[1]
try:
with open (path,"r") as readline:
count = [line for line in readline]
print len(count)
except IOError as e:
print "Sorry, the file %s is not exist" %(sys.argv[1])
print e
תרגיל 3 חריגים
אני לא יודע אם אני בכלל בכיוון אבל אחרי שיטוטים וחיפושים עצמיים החלטתי לכתוב “משהו” ולראות איך להתקדם משם:
מה שאני מבין מהקוד שכתבת הוא שיש אובייקט img שמקבל שם תקין של קובץ ואמור לפתוח קובץ אא"כ הוא מקבל שם לא תקין ואז מופעלת הפונקציה InvalidImageExt שמפעילה את הפונקציה test_bad_ext שמייצרת assert ומסיימת את התוכנית.
הקיצר , התבלבלתי לגמרי
import unittest
class TestImageFile(unittest.TestCase):
def __init__(self,name):
self.name = r"C:\Python\Object_Oriented_7" + name
def test_good_ext(self):
try:
img = ImageFile("file.png")
open(self.name,"a")
except InvalidImageExt:
self.fail("png should be a valid file extension")
def test_bad_ext(self):
with self.assertRaises(InvalidImageExt):
img = ImageFile("file.mp3")
def InvalidImageExt(self):
self.test_bad_ext()
if __name__ == '__main__':
unittest.main()
באמת כדאי לקחת צעד אחורה.
כשאני מקליד את התרגיל המקורי ומפעיל אני מקבל את התוצאה:
======================================================================
ERROR: test_bad_ext (__main__.TestImageFile)
----------------------------------------------------------------------
Traceback (most recent call last):
File "b.py", line 11, in test_bad_ext
with self.assertRaises(InvalidImageExt):
NameError: global name 'InvalidImageExt' is not defined
======================================================================
ERROR: test_good_ext (__main__.TestImageFile)
----------------------------------------------------------------------
Traceback (most recent call last):
File "b.py", line 7, in test_good_ext
except InvalidImageExt:
NameError: global name 'InvalidImageExt' is not defined
----------------------------------------------------------------------
Ran 2 tests in 0.000s
הודעת השגיאה הרלוונטית מתוך כל הפלט הזה היא:
NameError: global name 'InvalidImageExt' is not defined
אז תתחיל משם- איפה משתמשים בשם InvalidImageExt? מה זה אומר לגביו?
- מה שנראה לי הוא שמשתמשים בו כאשר שם הקובץ אינו תקין.
מצד אחד כיון שהוא מתחיל באות גדולה הוא נראה לי כמו מחלקה נוספת המטפלת במצב חריג אך מצד שני קח למשל את השורה:
with self.assertRaises(InvalidImageExt):
זה נראה כמו קריאה לפונקציה ולא למחלקה
- גם לא הבנתי את
("img = ImageFile("file.png
זה נראה כמו יצירת אוביקט בשם img אבל לאן בדיוק הארגומנט file.png הולך?
אין פה שום פונקציית __init__
שתקבל את הארגומנט הזה כמו שעשינו בתרגילים קודמים ?
- האמת היא שאני לא רואה קריאה לאף פונקציה אז איך בכלל התוכנית עובדת?
אבל זה כנראה טמון בשורה()unittest.main
תבנית ההפעלה והקריאה לפונקציות כאן שונה מהרגיל (לפחות ממה שהכרתי עד עכשיו) ולכן מבלבלת
אני חושב שיותר נכון להגיד שזו מחלקה שעוברת בתור פרמטר לפונקציה sefl.assertRaises. בוא ננסה להסתכל על עוד קטע:
def test_good_ext(self):
try:
img = ImageFile("file.png")
except InvalidImageExt:
self.fail("png should be a valid file extension")
כאן כבר ממש ברור מהשימוש אחרי המילה except שאכן יש לך עסק עם מחלקה שמייצגת Exception.
תמשיך מכאן ותתחיל לבנות את המחלקה הזו. מה הקוד המלא של מחלקה שאפשר לכתוב אחרי except כלומר מחלקה שמייצגת Exception?
אחרי זה באמת אפשר להמשיך לשורה השניה שלא הבנת:
img = ImageFile("file.png")
ואחרי שנסיים עם בעיית המחלקה החסרה תראה שגם פייתון לא ישמח במיוחד מהשורה הזאת והחלק השני יהיה באמת לכתוב כזו פונקציית init כמו שתיארת.
טוב, אז נתחיל מהשורה :except InvalidImageExt
ונגדיר מחלקה בשם InvalidImageExt אשר תחזיר Exception למי שקרא לה כלומר ל except בפונקציה test_good_ext
class InvalidImageExt(error):
self.error = error
raise Exception("invalid image {}".format(self.error))
אבל עדיין לא ברור לי הפורמט.
מי בדיוק קורא לפונקציות בתוך המחלקה ImageFile?
אני לא רואה כאן שום קוד כזה…
ואותו דבר ביחס לפונקציה test_bad_ext גם לה אף אחד לא קורא ולא ברור לי מתי היא מתופעלת.
מישהו אמר לי שפורמט unittest הוא בכלל פורמט לבדיקת הקוד שלי והקוד נמצא במקום אחר. האם זה נכון? לא הבנתי את זה מהתרגיל !
טוב התחלתי מלבנות את המחלקות Imagefile ו InvalidImageExt (אשר ייעשה בה שימוש בבדיקות יחידה)
למה זה לא עובד לי ???
למה לא נפתח קובץ תמונה ??
import os
class Imagefile(object):
def __init__(self, type):
self.types = ["jpg", "png", "tif", "gif"]
self.type = type
self.file = ''
self.path = r'C:\Python\Object_Oriented_7' + '\n' + self.type
for self.suffix in self.types:
if self.type.endswith(self.suffix):
self.file = open(self.path,"r")
else:
raise InvalidImageExt(self.type)
class InvalidImageExt(Exception):
def __init__(self, error):
super(InvalidImageExt, self).__init__()
self.error = error
pass
img = Imagefile("file.jpg")
הי,
יש פה כמה בעיות, אבל לפני שאפשר יהיה להגיע אליהן כדאי לשפר את המבנה:
אין צורך לבדוק שהקובץ קיים, מספיק לבדוק שהסיומת תקינה. לכן הייתי מוותר על הקוד שמנסה לפתוח את הקובץ. כמו כן הייתי מוותר על חיפוש הקובץ בתיקיה מסוימת וכו׳. קח רק את שם הקובץ וגזור ממנו את הסיומת ולאחר מכן תבדוק אם הסיומת שייכת לאחת הסיומות שאתה צריך.
חשוב גם לשים לב לבעיה מבנית בקוד שלך בתוך לולאת ה for: המטרה של הקוד לבדוק שהקוד מסתיים באחת הסיומות מבין רשימת הסיומות שכתבת. בלולאה לעומת זאת מספיק שסיומת אחת לא תצליח כדי לזרוק את השגיאה. זה צריך להיות הפוך: רק אם אף אחת מהסיומות לא התאימה אז צריך לזרוק את השגיאה.
טוב , ניסיתי לשפר.
עד השורה return True זה עובד טוב (למרות שכשכתבתי להדפיס משהו במקום return True זה לא הדפיס אז אולי אני רק חושב שזה עובד טוב) ובכל מקרה לא קיבלתי errors כשהרצתי.
על כל פנים כשמגיעים לשורה אח"כ שאמורה לטפל בחריגים זה לא עובד.
תוכל להחכימני?
import os
class Imagefile(object):
def __init__(self, type):
self.types = ["jpg", "png", "tif", "gif"]
self.type = type
self.suffix = os.path.splitext(self.type[1])
if self.suffix in self.types:
return True
else:
raise InvalidImageExt("Wrong type{}".format(self.type))
class InvalidImageExt(Exception):
def __init__(self, error):
super(InvalidImageExt, self).__init__()
self.error = error
pass
img = Imagefile("file.jpg")
אני חושב שהקוד שלך לחישוב הסיומת שגוי. נסה להוסיף הודעות הדפסה כדי לראות מה שם הקובץ המלא שעובר ומה הסיומת שאתה מוצא (במשתנה self.suffix) ותראה שהסיומת שאתה מוצא היא לא הסיומת האמיתית של הקובץ.
אחרי זה תראה איך אתה מוצא את הסיומת הנכונה ותמשיך משם.
תלמידה שאלה לגבי הקוד הבא - מדוע מדי פעם הוא ״נעצר״ ומחכה לקלט פעם שניה לפני שמדפיס פידבק למשתמש:
"""
random anumber between 1-100, u have to guess the num
"""
import random
while True:
print("do u wanna play?")
if not input()=="YES":
break
print("Let's Go!")
print("guess a number between 1-100")
game=random.randrange(1,100)
finGame=True
while finGame==True:
if int(input())>game:
print ("ouch! the guess is too big, try again")
else:
if int(input())<game:
print ("ouch! the guess is too small, try again")
else:
print("nice try!!!!!!!! this guess was hwosome!",game)
finGame=False
קודם כל נסי לאפיין את המצבים בהם הבעיה קורית (דרך ניסוי וטעיה).
אחרי שהבנת מתי זה קורה נסי לעקוב אחר המסלול בקוד שגורם לבעיה ולבחון מה קורה שם - איזה רצף של פקודות מופעל ולמה רצף זה גורם לבעיה?
אתה מתכוון למשהו כזה?
ואז הקוד שאתה כתבת בתרגיל בודק את הקוד הזה ע"י unittest?
class ImageFile(object):
def __init__(self, type):
self.types = ["jpg", "png", "tif", "gif"]
self.type = type
self.suffix = self.type.split('.')[1]
if self.suffix in self.types:
print self.suffix
else:
raise InvalidImageExt("Wrong type{}".format(self.type))
class InvalidImageExt(Exception):
def __init__(self, error):
super(InvalidImageExt, self).__init__()
self.error = error
img = ImageFile("file.gif")
מדויק! (ובדרך כלל אני לא משאיר הודעות קצרות כאלה אבל הפעם זה התבקש.)
הי ינון,
הקוד הבא מבצע חישוב של שורש של מספרים משורת הפקודה
הכנסתי את הנתונים הבאים בשורת הפקודה:
10
9-
p
81
(10 ראשון , 81 אחרון)
משום מה כשהוא מגיע ל 81 הוא זורק לי IndexError: list index out of range
לא מבין למה
import sys
import math
def sqrt(x):
return math.sqrt(x)
a = []
for index,number in enumerate(sys.argv[1:]):
print 'number {} in place {} the root is:'.format(number,index)
try:
a.append(float(number))
print sqrt(a[index])
except ValueError as e:
print "Please enter numbers > 0 only"
print e.message
הבנתי מה הבעיה ותיקנתי
import sys
import math
def sqrt(x):
return math.sqrt(x)
a = []
for number in (sys.argv[1:]):
try:
a.append(float(number))
print 'number {} in place {} the root is:'.format(number,len(a)-1)
print sqrt(a[-1])
except ValueError as e:
print "Please enter numbers > 0 only"
print e.message