Αποστολέας Θέμα: Βρείτε το λάθος!!!  (Αναγνώστηκε 2023 φορές)

evry

  • Γενικός διαχειριστής
  • *****
  • Μηνύματα: 3059
  • to Iterate is human to Recurse divine
Βρείτε το λάθος!!!
« στις: 09 Φεβ 2017, 08:22:08 μμ »
Προσπαθώντας να λύσω μια άσκηση του τετραδίου μαθητή στην οποία ζητείται να διαχωριστεί μια λίστα αριθμών σε δυο λίστες θετικών και αρνητικών υλοποίησα την παρακάτω "αφελή" λύση:
Κώδικας: Python
  1. def splitbySign(L):
  2.     positives = negatives = []
  3.     for number in L:
  4.         if number > 0 :
  5.             positives.append(number)
  6.         elif number < 0 :
  7.             negatives.append(number)
  8.     print positives
  9.     print negatives
  10.  
Αν εκτελέσουμε τον παρακάτω κώδικα η απάντηση που θα πάρουμε δεν είναι σωστή.
Που είναι το λάθος? Γιατί συμβαίνει αυτό? Πως θα το διορθώσουμε χωρίς να πειράξουμε τον κώδικα μέσα στην επανάληψη?

Στο βιβλίο υπάρχει αντίστοιχο παράδειγμα το οποίο όμως είναι υλοποιημένο ως εξής και το οποίο δουλεύει σωστά!
Κώδικας: Python
  1. def splitbySign2(L):
  2.     positives = negatives = []
  3.     for number in L:
  4.         if number > 0 :
  5.             positives = positives + [number]
  6.         elif number < 0 :
  7.             negatives = negatives + [number]
  8.     print positives
  9.     print negatives
  10.  
Αυτό γιατί δουλεύει?

Αναφέρω το παραπάνω πρόβλημα γιατί το θεωρώ ενδιαφέρον.
Κάτι τέτοια παραδείγματα δείχνουν ότι πρέπει να επικεντρωνόμαστε στις βασικές έννοιες και όχι στην ασκησεολογία.
What I cannot create I do not understand -- Richard Feynman
http://evripides.mysch.gr

taxata

  • Βετεράνος
  • ****
  • Μηνύματα: 87
  • Live long and prosper \\//
    • Πληροφορική στο ΕΠΑΛ
Απ: Βρείτε το λάθος!!!
« Απάντηση #1 στις: 09 Φεβ 2017, 09:07:33 μμ »
Ενδιαφέρoυσα σπαζοκεφαλιά για επίδειξη στο μάθημα :D

Αρχικά το λάθος βρίσκεται στο positives = negatives = [] διότι δείχνουν στην ίδια θέση μνήμης οπότε κάθε εισαγωγή ενός νέου στοιχείου αφορά και στις δύο λίστες.
---
Στη συνέχεια δεν προκύπτει λάθος γιατί η εντολή  positives = positives + [number] ξαναορίζει νέα λίστα positives & negatives αντίστοιχα

μπορούν να εξηγηθούν στους μαθητές  με τη βοήθεια της εντολής id, id(positives).

Να ακόμα ένα λάθος
Κώδικας: Python
  1. # Δημιουργία αντιγράφου λίστας
  2. first = [1, 2, 3]
  3. second = first
  4. first.append(4)
  5. print first, second
  6.  
οπότε θα προκύψει και το  εύλογο ερώτημα: Πως κάνουμε αντίγραφο μίας λίστας οέο  >:(
« Τελευταία τροποποίηση: 09 Φεβ 2017, 09:32:09 μμ από taxata »
Τάσος_Χατζηπαπαδόπουλος
http://users.sch.gr/chatzipap/

itt

  • Δεινόσαυρος
  • *****
  • Μηνύματα: 426
  • Real stupidity beats ΑΙ any time
Απ: Βρείτε το λάθος!!!
« Απάντηση #2 στις: 09 Φεβ 2017, 09:39:22 μμ »
Προσπαθώντας να λύσω μια άσκηση του τετραδίου μαθητή στην οποία ζητείται να διαχωριστεί μια λίστα αριθμών σε δυο λίστες θετικών και αρνητικών υλοποίησα την παρακάτω "αφελή" λύση:
Κώδικας: Python
  1. def splitbySign(L):
  2.     positives = negatives = []
  3.     for number in L:
  4.         if number > 0 :
  5.             positives.append(number)
  6.         elif number < 0 :
  7.             negatives.append(number)
  8.     print positives
  9.     print negatives
  10.  
Αν εκτελέσουμε τον παρακάτω κώδικα η απάντηση που θα πάρουμε δεν είναι σωστή.
Που είναι το λάθος? Γιατί συμβαίνει αυτό? Πως θα το διορθώσουμε χωρίς να πειράξουμε τον κώδικα μέσα στην επανάληψη?

Στο βιβλίο υπάρχει αντίστοιχο παράδειγμα το οποίο όμως είναι υλοποιημένο ως εξής και το οποίο δουλεύει σωστά!
Κώδικας: Python
  1. def splitbySign2(L):
  2.     positives = negatives = []
  3.     for number in L:
  4.         if number > 0 :
  5.             positives = positives + [number]
  6.         elif number < 0 :
  7.             negatives = negatives + [number]
  8.     print positives
  9.     print negatives
  10.  
Αυτό γιατί δουλεύει?

Αναφέρω το παραπάνω πρόβλημα γιατί το θεωρώ ενδιαφέρον.
Κάτι τέτοια παραδείγματα δείχνουν ότι πρέπει να επικεντρωνόμαστε στις βασικές έννοιες και όχι στην ασκησεολογία.

Τέτοια παραδείγματα (που σημειωτέον η υλοποίηση του βιβλίου ειναι βλακώδης) δείχνουν πόσο δύσκολο (και σημαντικό) είναι να καταλάβει κανείς την διαφορά μεταξύ αντικειμένου και reference σε αντικείμενο.

Δηλαδή ότι το second = first στο παράδειγμα του taxata είναι pointer assignment και όχι object copy.

taxata

  • Βετεράνος
  • ****
  • Μηνύματα: 87
  • Live long and prosper \\//
    • Πληροφορική στο ΕΠΑΛ
Απ: Βρείτε το λάθος!!!
« Απάντηση #3 στις: 09 Φεβ 2017, 10:04:49 μμ »
Ο δρόμος προς την τελειότητα είναι στρωμένος με λάθη ...
Κώδικας: Python
  1. a = 1
  2. b = a
  3. b = 2
  4. print a, b
  5. # ---------------
  6. a = [1]
  7. b = a
  8. b[0] = 2
  9. print a, b
  10.  
τι έγινε εδώ βρε παιδιά :o
Τάσος_Χατζηπαπαδόπουλος
http://users.sch.gr/chatzipap/

evry

  • Γενικός διαχειριστής
  • *****
  • Μηνύματα: 3059
  • to Iterate is human to Recurse divine
Απ: Βρείτε το λάθος!!!
« Απάντηση #4 στις: 09 Φεβ 2017, 10:12:47 μμ »
και αυτό έχει ενδιαφέρον:
Κώδικας: Python
  1. A = [1, 2, 3, 4]
  2. L = [A, A, A]
  3. L[1][1] = 100
  4. print L
  5. print A
What I cannot create I do not understand -- Richard Feynman
http://evripides.mysch.gr

pgrontas

  • Ομάδα διαγωνισμάτων 2016
  • *
  • Μηνύματα: 1302
  • There are always possibilities...
Απ: Βρείτε το λάθος!!!
« Απάντηση #5 στις: 09 Φεβ 2017, 11:31:35 μμ »
Επεμβαίνω, αν και δεν διδάσκω, το μάθημα, αλλά έχω τις εξής παρατηρήσεις:

Στο αρχικό 'λάθος' του Ευριπίδη για ποιον λόγο να χρησιμοποιήσεις το ιδίωμα της διπλής ανάθεσης στο positives = negatives = []. Προσφέρει κάτι (αλγοριθμικά / εννοιολογικά) στον τρόπο σκέψης των μαθητών;

Τέτοια παραδείγματα (που σημειωτέον η υλοποίηση του βιβλίου ειναι βλακώδης) δείχνουν πόσο δύσκολο (και σημαντικό) είναι να καταλάβει κανείς την διαφορά μεταξύ αντικειμένου και reference σε αντικείμενο.
Επιπλέον δείχνουν και την αποτυχία πολλών σύγχρονων γλωσσών προγραμματισμούν να το κάνουν σαφές στον προγραμματιστή  ;)
A man provided with paper, pencil, and rubber, and subject to strict discipline is in effect a universal machine - Alan Turing

evry

  • Γενικός διαχειριστής
  • *****
  • Μηνύματα: 3059
  • to Iterate is human to Recurse divine
Απ: Βρείτε το λάθος!!!
« Απάντηση #6 στις: 10 Φεβ 2017, 08:38:20 πμ »
Η χρήση του τελεστή + για συνένωση λιστών νομίζω ότι είναι μια καλή στρατηγική για να ξεκινήσεις στις λίστες, αφού ήδη οι μαθητές έχουν δει τον ίδιο τελεστή συνένωσης στα αλφαριθμητικά. Άρα μειώνεις τον διδακτικό θόρυβο και εισάγεις κάποιες βασικές έννοιες πιο γρήγορα και εύκολα. Αφού δεις ότι έχουν καταλάβει την έννοια της λίστας τότε μπορείς να μιλήσεις για την append και να εξηγήσεις γιατί πρέπει να χρησιμοποιούν αυτήν.
Δεν χρειάζεται να δείχνουμε πάντα την καλύτερη υλοποίηση. Το σκεπτικό είναι να διευκολύνουμε τους μαθητές επειδή υπεισέρχονται πολλές νέες έννοιες.

Τώρα όσον αφορά την εντολή
Κώδικας: Python
  1. positives = negatives = [ ]
πράγματι δεν υπάρχει κάποιο σκεπτικό. Μας ξέφυγε. :-[
Ωστόσο τώρα που το βλέπω είναι μια αφορμή να δώσεις στους μαθητές το τμήμα του προβληματικού κώδικα και να γίνει μια συζήτηση μέσα στην τάξη
What I cannot create I do not understand -- Richard Feynman
http://evripides.mysch.gr

zsdregas

  • Θαμώνας
  • ***
  • Μηνύματα: 48
  • You can't outsmart me cause I am a moron
Απ: Βρείτε το λάθος!!!
« Απάντηση #7 στις: 10 Φεβ 2017, 10:23:22 πμ »
Για να σιγουρευτώ, στην πρώτη περίπτωση έχουμε object copy και στη δεύτερη pointer assignment;

Κώδικας: Python
  1. a = 1
  2. b = a
  3. b = 2
  4. print a, b
  5. # ---------------
  6. a = [1]
  7. b = a
  8. b[0] = 2
  9. print a, b
  10.  

itt

  • Δεινόσαυρος
  • *****
  • Μηνύματα: 426
  • Real stupidity beats ΑΙ any time
Απ: Βρείτε το λάθος!!!
« Απάντηση #8 στις: 10 Φεβ 2017, 03:33:25 μμ »
Κοιτά για να το θέσουμε σωστά (δηλαδή pythonικά) το a και b, είναι 2 bindings σε ένα object.

Τα πάντα στην python είναι object (ακόμα και οι ακέραιοι στην περίπτωσή μας). Κάποια object είναι immutable όμως (όπως οι ακέραιοι).

Το a = 2, σημαίνει ότι κάνεις bind το a σε ένα int object με την τιμή 2.

To b = a σημαίνει ότι το b κάνει bind στο object που έχει γίνει bind το a.

Δεν υπάρχει κανένα copy. Μπορείς και εσύ να κάνεις verify ότι το b = a, αφού ισχύει id(b) == id(a), εαν το τρέξεις σε έναν interpreter.

Ομοίως και το δεύτερο, απλά στο δεύτερο το object είναι μία λίστα.


aprekates

  • Βετεράνος
  • ****
  • Μηνύματα: 87
    • Enomem
Απ: Βρείτε το λάθος!!!
« Απάντηση #9 στις: 16 Μάρ 2017, 12:29:05 μμ »
Συνοπτικά από τα παραδείγματα των συναδέλφων προκύπτει υπάρχει πρόβλημα ορθής κατανόησης:
1) Της σημασιολογίας της χρήσης των μεταβλητών στην python (variable semantics)
2) Της σημασιολογίας και τον μηχανισμός υλοποιήσης του περάσματος ορισμάτων σε μια συνάρτηση.
Στη wikipedia αναφέρεται και σαν Evaluation strategy
Ως προς την σημασιολογία των μεταβλητών κατατοπιστικό μου φάνηκε και το: Understanding python variables


Όπως γράφει και ο itt στην python μια εντολή ανάθεσης τιμής (assignment statement)
συσχετίζει (binds) ένα όνομα με ένα αντικείμενο.
Ένα όνομα δεν μπορεί να συσχετιστεί με άλλο όνομα παρά μόνο με αντικέιμενο.
>> a = 0   # ok
>> a = b   
NameError: name 'c' is not defined


Αν αντιπαραβάλεις από την μια των κώδικα του διαχωρισμού λίστας και της υλοποίησης της διεπαφής της στοιβας (την διορθωμένη)  ή χρήση ή όχι της append δεν είναι εύκολη για καθηγητή πόσο μάλλον για μαθητή.

Υλοποίηση Στοίβας
Κώδικας: Python
  1. def push(stack, item) :
  2.   stack.append( item )
  3.  
  4. def pop(stack) :
  5.   return stack.pop( )
  6.  
  7. def isEmpty(stack) :
  8.  return len(stack) == 0
  9.  
  10. def createStack( ) :
  11.  return [ ]
  12.  



Κώδικας: Python
  1. positives = negatives = [ ]
  2. for number in numbers :        
  3.  # για κάθε αριθμό της λίστας
  4.    if number > 0 :
  5.         # αν είναι θετικός
  6.         positives = positives + [ number ]
  7.        # πρόσθεσέ τον στη λίστα με τους θετικούς
  8.    else :
  9.        negatives = negatives + [ number ]
  10. # αλλιώς στη λίστα με τους αρνητικούς
  11. print positives
  12. print negatives

Διαχωρισμός λίστας σε pythontutor

Ο Διαχωρισμός λίστας  με την append που δεν λειτουργεί στο pythontutor


Ενδιαφέρον και κατατοπιστικό στο θέμα είναι και το Is Python pass-by-reference or pass-by-value?

Λίγο αργά βρήκα και τη σχετική συζήτηση σε άλλο νήμα : Διορθώσεις Βιβλίου Προγραμματισμός Υπολογιστών Γ ΕΠΑΛ

Κώδικας: Python
  1.   def test(mylist):
  2.         mylist[0] = mylist[1] = 100
  3.      
  4.   >>> a = [2, 4, 5]
  5.   >>> test( a )
  6.   >>> print a
  7.   [100,100,5]
  8.  

Αυτό το παράδειγμα του evry δείχνει ότι δεν εχουμε call by value .

Για το παράδειγμα του taxata (πως δημιουργούμε αντίγραφο λίστας;

Κώδικας: Python
  1. >> # Δημιουργία αντιγράφου λίστας
  2. >>first = [1, 2, 3]
  3. >> second = first
  4. >> first.append(4)
  5. >> print first, second
  6. [1,2,3,4],[1,2,3,4]
  7.  

η απάντηση είναι στην δραστηριότητα 5.3.4 του βιβλίου της Β :
Κώδικας: Python
  1. >>> a = [5,8,13,21,34]
  2. >>> b = a[:]
  3. >>> d = a
  4. >>> a.pop()
  5. 34
  6. >>> d.pop()
  7. 21
  8. >>> a[0]=a[1]=6
  9. >>> print a,b,d
  10. [6, 6, 13] [5, 8, 13, 21, 34] [6, 6, 13]
  11. >>> # η λίστα b δεν άλλαξε
  12.  

Διαδραστική αποσφαλμάτωση του παραπάνω κώδικα στο pythontutor.com

Local variable referenced before assignment in Python? Μια ακόμη εξήγηση για το παράδειγμα του msoukara :

Κώδικας: Python
  1. x = 50
  2. def func():
  3.      print('Το x είναι', x)          
  4.      x = 2
  5.      print('Το τοπικό x άλλαξε σε', x)
  6. func()
  7. print('Το x είναι ακόμα', x)
  8. # UnboundLocalError: local variable 'x' referenced before assignment

ΥΓ:  μεταφέρω-αντιγραφω σκόρπια παραδειγματα προκειμένου ισως να φανεί καλύτερα το ζητούμενο
« Τελευταία τροποποίηση: 21 Μάρ 2017, 12:42:15 μμ από aprekates »

evry

  • Γενικός διαχειριστής
  • *****
  • Μηνύματα: 3059
  • to Iterate is human to Recurse divine
Απ: Βρείτε το λάθος!!!
« Απάντηση #10 στις: 19 Μάρ 2017, 07:25:37 μμ »
Επειδή ειδικά τα τελευταία μηνύματα δεν είχαν απολύτως καμία σχέση με το θέμα του thread.
Στο παρακάτω thread μεταφέρθηκαν τα μηνύματα σχετικά με το πόσο ακατάλληλη είναι η Python για την εκπαίδευση:
Είναι η Python Εκπαιδευτική γλώσσα?

και στο παρακάτω μπορείτε να γράψετε ότι θέλετε περί φιλοσοφίας, μαθηματικών, πληροφορικής κλπ
Δείκτες, Αριθμητική Peano, Φιλοσοφία κλπ

Υπάρχει πάντως και η απόδειξη του Godel για την ύπαρξη του Θεού που ταιριάζει αρκετά θα έλεγα στο παραπάνω thread!
Gödel's ontological proof

αφού συνδυάζει μαθηματικά, φιλοσοφία και ... πληροφορική
Automating Godel’s Ontological Proof of God’s Existence with Higher-order Automated Theorem Provers

Παρακαλώ στο thread αυτό μόνο μηνύματα σχετικά με το αρχικό πρόβλημα που έθεσα και είναι πολύ σημαντικό στην διδακτική πράξη.  :police:
« Τελευταία τροποποίηση: 19 Μάρ 2017, 08:42:52 μμ από evry »
What I cannot create I do not understand -- Richard Feynman
http://evripides.mysch.gr