Προς το περιεχόμενο

Προτεινόμενες αναρτήσεις

Δημοσ.

@migf1 @offtopic
Δεν έχω μεγάλη εμπειρία ούτε με την python ούτε με οποιαδήποτε γλώσσα προγραμματισμού αλλά έχω μια ένσταση όσων αφορά αυτά που λες πιο πάνω για τον python way. Για τον C++ way δεν έχω ιδέα διότι δεν γνωρίζω C++, αλλά φαντάζομαι ότι υπάρχουν λόγοι.

Ας πάρουμε ένα απλό πρόβλημα. Τη δημιουργία μιας συνάρτησης σε python που επιστρέφει True αν δύο strings αποτελούνται απ' τα ίδια ακριβώς γράμματα.

Ένας που μόλις ασχολήθηκε με την γλώσσα και έμαθε το συντακτικό της και τα βασικά της ίσως πρότεινε κάτι τέτοιο σαν λύση:

def f(s1, s2):
    for i in s1:
        if not i in s2:
            return False
    for i in s2:
        if not i in s1:
            return False
    return True


Κάποιος που χει έχει ασχοληθεί λίγο παραπάνω με τη γλώσσα και ξέρει τις built-in functions θα μπορέσει να δώσει τη λύση σε one-liner:

def f(s1, s2):
    return all(i in s2 for i in s1) and all(i in s1 for i in s2)


Ήδη πιο σύντομη και πιο readable λύση.
Ο ακόμα πιο έμπειρος pythonistas θα έγραφε απλά:

def f(s1, s2):
    return set(s1) == set(s2)


Ε αναμφισβήτητα το τελευταίο είναι πολύ πιο σύντομο, καθαρό και κομψό απ' το πρώτο και το βρίσκω απόλυτα λογικό να σου προτείνουν να το γράψεις έτσι.

Άλλο πρόχειρο παράδειγμα που μου 'ρχεται είναι η χρήση της enumerate() σε ένα loop αντί να κρατάς έναν counter χειροκίνητα. Και πάρα πολλά άλλα.

Δεν ξέρω αν υπάρχει "the python way", αλλά σίγουρα - και ευτυχώς κατ' εμέ - υπάρχει "more pythonic way".

Δημοσ.

@migf1 βασικά τα λόγια είναι τζάμπα. "Well written C tends to be legal C++ also". Ξέρεις τι είναι well-written C αλλά δεν είναι legal C++? Αυτό:

int* p = malloc(sizeof(int));

Σα να λέμε μια τόση δα μικρή ασήμαντη (recommended practice από τους πάντες όταν γράφεις C, υποθέτω θα την έχεις συστήσει και συ ο ίδιος εδώ στο foru,), σπάνια (την έχουμε αναφέρει πόσες φορές λέει εδώ στο forum?) λεπτομέρεια που ακόμα και κάποιος γνώστης C και C++ όπως εσύ μπορεί να παραβλέψει.

 

Τα υπόλοιπα περί μικρού vs μεγάλου breakage (πως λέμε no true scotsman) θα ήθελα να δω να συζητούνται, αλλά επειδή δεν είμαι διατεθειμένος να συμμετέχω στη συζήτηση μάλλον θα μείνω με την όρεξη.

 

Ξέρεις υπάρχουν κάποια πράγματα που αν τα έλεγε οποιοσδήποτε άλλος θα είχε διαφορετική αντιμετώπιση, αλλά έχεις την ατυχία να στοχοποιείσαι αδίκως, και να είμαι τώρα εγώ εδώ να λέω πράγματα όπως τα παραπάνω και όπως τα παρακάτω:

  1. O migf1 έχει δηλώσει πως δεν ξέρει SQL γιατί "δεν του χρειάστηκε ποτέ" (μη με βάλεις να βρω το link).
  2. O migf1 έχει δηλώσει πως "ξέρει PHP".
  3. Την οποία έμαθε προγραμματίζοντας nontrivial εφαρμογές (μαθαίνει κανείς αλλιώς?).
  4. Άρα ο migf1 έμαθε PHP προγραμματίζοντας nontrivial εφαρμογές που... δεν είχαν πάρε δώσε με SQL.

Δε νομίζω ότι χρειάζεται παραπάνω σχολιασμός εδώ.

 

By the way, είμαι σίγουρος πως λόγω των πολλών γνώσεων που έχεις (δίχως άλλο και C# μέσα σ' αυτές) μπέρδεψες και κάτι άλλο: η C++ δεν έχει generics αλλά templates. Εδώ καλό είναι να δείξουμε κάποια κατανόηση μιας και οποιοσδήποτε μπορεί να κάνει ένα τέτοιο λάθος, εφάμιλλο ας πούμε του να πεις ένα αυτοκίνητο μηχανάκι. Στο κάτω κάτω και τα δύο έχουν ρόδες και τα χρησιμοποιούμε για να πάμε απ' το ένα μέρος στο άλλο.

 

Αυτά. Είχαν γεμίσει τα σακουλάκια μου βλέπεις και έπρεπε να τ' αδειάσω.

 

Δεν έχω μεγάλη εμπειρία ούτε με την python ούτε με οποιαδήποτε γλώσσα προγραμματισμού αλλά έχω μια ένσταση όσων αφορά αυτά που λες πιο πάνω για τον python way. Για τον C++ way δεν έχω ιδέα διότι δεν γνωρίζω C++, αλλά φαντάζομαι ότι υπάρχουν λόγοι.

 

Εκεί έχουν ένσταση αυτοί που γνωρίζουν C++, αλλά τον αράπη κι αν τον πλένεις...

Δημοσ.

@ilias:

 

 

@migf1 @offtopic

Δεν έχω μεγάλη εμπειρία ούτε με την python ούτε με οποιαδήποτε γλώσσα προγραμματισμού αλλά έχω μια ένσταση όσων αφορά αυτά που λες πιο πάνω για τον python way. Για τον C++ way δεν έχω ιδέα διότι δεν γνωρίζω C++, αλλά φαντάζομαι ότι υπάρχουν λόγοι.

 

Ας πάρουμε ένα απλό πρόβλημα. Τη δημιουργία μιας συνάρτησης σε python που επιστρέφει True αν δύο strings αποτελούνται απ' τα ίδια ακριβώς γράμματα.

 

Ένας που μόλις ασχολήθηκε με την γλώσσα και έμαθε το συντακτικό της και τα βασικά της ίσως πρότεινε κάτι τέτοιο σαν λύση:

 

 

def f(s1, s2):
    for i in s1:
        if not i in s2:
            return False
    for i in s2:
        if not i in s1:
            return False
    return True
Κάποιος που χει έχει ασχοληθεί λίγο παραπάνω με τη γλώσσα και ξέρει τις built-in functions θα μπορέσει να δώσει τη λύση σε one-liner:

def f(s1, s2):
    return all(i in s2 for i in s1) and all(i in s1 for i in s2)
Ήδη πιο σύντομη και πιο readable λύση.

Ο ακόμα πιο έμπειρος pythonistas θα έγραφε απλά:

def f(s1, s2):
    return set(s1) == set(s2)
Ε αναμφισβήτητα το τελευταίο είναι πολύ πιο σύντομο, καθαρό και κομψό απ' το πρώτο και το βρίσκω απόλυτα λογικό να σου προτείνουν να το γράψεις έτσι.

 

 

 

Άλλο πρόχειρο παράδειγμα που μου 'ρχεται είναι η χρήση της enumerate() σε ένα loop αντί να κρατάς έναν counter χειροκίνητα. Και πάρα πολλά άλλα.

 

Δεν ξέρω αν υπάρχει "the python way", αλλά σίγουρα - και ευτυχώς κατ' εμέ - υπάρχει "more pythonic way".

 

Ούτε εγώ ξέρω Python, αλλά πες μου για παράδειγμα πoιο από τα παρακάτω είναι "more Pythonic way" και γιατί: 

mylist = [1,2,3,4]
# είναι αυτό pythonic way;
for item in mylist:
	print( item )

# ή είναι αυτό;
for pair in enumerate(mylist):
	print( pair[1] )

# μήπως είναι και τα δυο; 
Άλλο παράδειγμα:

# είναι αυτό pythonic way;
mylist = []
for i in range(5):
	mylist.append(i)
print( mylist )

# ή είναι αυτό;
mylist = [i for i in range(5)]
print( mylist )

# μήπως είναι και τα δυο; 
Άλλο παράδειγμα, το config.py πως είναι πιο "pythonic way" να το υλοποιήσεις (και γιατί)...

 

έτσι...

'''config.py'''

# GUI strings
S1 = '1'
S2 = '2'

# Other strings
S3 = '3'
S4 = '4'
...
έτσι...

'''config.py'''

class GuiStrings:
    S1 = '1'
    S2 = '2'

class OtherStrings:
    S3 = '3'
    S4 = '4'
...
έτσι...

'''config.py'''

class GuiStrings:
    def __init__( self )
        self.S1 = '1'
        self.S2 = '2'

class OtherStrings:
    def __init__( self )
        self.S3 = '3'
        self.S4 = '4'
...
έτσι...

'''config.py'''

class Globals:
    S1 = '1'
    S2 = '2'
    ...
και πάει λέγοντας. Οι συνδυασμοί είναι άπειροι. Με άλλους έχεις απευθείας access, με άλλους πρέπει πρώτα να κάνεις instantiate objects, με άλλους μπορείς να έχεις πρόσβαση κι έτσι κι αλλιώς, κλπ, κλπ.

 

Το κρίσιμο είναι μου απαντήσει και το ΓΙΑΤΙ το ένα είναι more pythonic από το άλλο (αν δηλαδή μου υποδείξεις κάποιο ως "more pythonic").

 

ΥΓ. Για την ισότητα των χαρακτήρων 2 strings δεν αρκεί ένα απλό == ?

def f(s1, s2):
	return s1 == s2
Αν αρκεί (δεν είμαι σίγουρος για αυτό ρωτάω) πως κατατάσσεται μια τέτοια υλοποίηση στην κλίμακα των "pythonic ways" συγκριτικά με τις άλλες υλοποιήσεις που έδειξες, και κυρίως γιατί;

 

 

 

@defacer:

 

 

Παίξε με τα σακουλάκια σου, με τις λέξεις και με την κοσμάρα σου όσο θέλεις. Είναι δικά σου προβλήματα που δεν με αφορούν.

 

Όμως, σε ότι αφορά τις δηλώσεις μου ναι ξέρω PHP και δεν ξέρω SQL. Και όσες φορές έχει χρειαστεί να ασχοληθώ εγώ με το SQL κομμάτι, τα έχω καταφέρει παραπάνω από μια χαρά, έχω πληρωθεί καλά, και οι πελάτες έχουν μένουν υπερ-ευχαριστημένοι. Σου αρέσει, δεν σου αρέσει.

 

 

Δημοσ.

@migf1

 

mylist = [1,2,3,4]
# είναι αυτό pythonic way;
for item in mylist:
    print( item )

# ή είναι αυτό;
for pair in enumerate(mylist):
    print( pair[1] )
# μήπως είναι και τα δυο; 

Κανένα απ' τα δύο. Το pythonic θα ήταν:

for i in range(1, 5):
    print(i)

Δεν φαίνεται η χρήση της enumerate στο παράδειγμα που έδωσες πιο πάνω. Ένα παράδειγμα στο οποίο θα φαινόταν είναι:

for num, s in enumerate(["zero", "one", "two"]):
    print(num, s)

Αντί για:

num = 0
for s in ["zero", "one", "two"]:
    print(num, s)
    num += 1

 

Άλλο παράδειγμα:

# είναι αυτό pythonic way;
mylist = []
for i in range(5):
    mylist.append(i)
print( mylist )

# ή είναι αυτό;
mylist = [i for i in range(5)]
print( mylist )
# μήπως είναι και τα δυο; 

 

Πάλι κανένα απ' τα δύο:

mylist = list(range(5))

Παρ' όλα αυτά ποτέ δεν είπα (ούτε και κανένας άλλος νομίζω) ότι there is only one way. Απλά υπάρχουν λύσεις που είναι πιο pythonic από κάποιες άλλες απ' την άποψη ότι εκμεταλλεύονται τις ιδίοτητες/σύνταξη/built-in funcs/built-in types της γλώσσας και καταλήγουν σε πιο simple, readable και elegant κώδικα. Μπορεί αυτές οι λύσεις να είναι παραπάνω από μία, αλλά ΔΕΝ είναι όλες οι λύσεις pythonic!

Σχετικά με το config που λες δεν νομίζω ότι τίθεται θέμα pythonic way γιατί στην κάθε περίπτωση το αποτέλεσμα είναι διαφορετικό. Όπως είπες με άλλον έχεις απευθείας access, αλλού δημιουργείς objects κλπ. Στα παραδείγματα που αναφέρθηκαν παραπάνω αντιθέτως δεν βρίσκω κανέναν λόγο να μην χρησιμοποιήσεις τον "pythonic way", αφού πάντα θα πάρεις ακριβώς το ίδιο αποτέλεσμα έχοντας λιγότερο και πιο clean κώδικα.
 

ΥΓ. Για την ισότητα των χαρακτήρων 2 strings δεν αρκεί ένα απλό == ?

 

Δεν μίλησα για ισότητα, αλλά για το αν αποτελούνται ακριβώς απ' τους ίδιους χαρακτήρες. Δηλαδή το f("abcD", cDDbaa") να δίνει True, ενώ το f("abc", "cbaf") να δίνει False.

 

Δημοσ.

 

 

@migf1

 

 

Κανένα απ' τα δύο. Το pythonic θα ήταν:

for i in range(1, 5):
    print(i)

 

Σόρι, αλλά εσύ εδώ αλλοίωσες το παράδειγμα. Εγώ αυτό που εννοούσα ήταν ποιος από τους 2 τρόπους (και κυρίως γιατί) είναι "more pythonic" για να τυπώσεις τα περιεχόμενα μιας λίστας (κι εσύ μου απαντάς πως το πιο pythonic είναι να τυπώνεις 5 ακέραιους)

 

Δεν φαίνεται η χρήση της enumerate στο παράδειγμα που έδωσες πιο πάνω. Ένα παράδειγμα στο οποίο θα φαινόταν είναι:

for num, s in enumerate(["zero", "one", "two"]):
    print(num, s)
Αντί για:

num = 0
for s in ["zero", "one", "two"]:
    print(num, s)
    num += 1

 

Πάλι μου απαντάς αλλοιώνοντας το παράδειγμα. Εγώ θέλω να τυπώσω τα περιεχόμενα μιας υπάρχουσας λίστας. Εσύ εδώ του βάζεις και αύξοντα αριθμό μπροστά.

 

Εγώ λοιπόν θα επιμείνω στην ερώτηση του αρχικού μου παραδείγματος, και θα προσθέσω κι άλλους τρόπους με τους οποίους μπορείς να τυπώσεις τα περιεχόμενα μια λίστας ένα σε κάθε γραμμή. Π.χ....

 

print( *mylist, sep= '\n' )                  # one-liner
print( '\n'.join(map(str, mylist)))          # another one-liner
print( '\n'.join(str(x) for x in mylist) )   # yet another one-liner
[print(x) for x in mylist]                   # oh yes, yet another one-liner
print( ''.join( [str(x) for x in mylist] ) ) # guess what, yet another one-liner

Όταν λοιπόν η γλώσσα σου παρέχει 1000 διαφορετικούς τρόπους να κάνεις ένα πράγμα, και τον καθένα από αυτούς τους τρόπους μπορείς να τους χρησιμοποιήσεις σε κυριολεκτικά άπειρα contexts, με ποιο ακριβώς κριτήριο θα χαρακτηρίσεις ποιος είναι more pythonic από τους άλλους; Π.χ. έχω διαβάσει πως στην Python 2 τα maps είναι ταχύτερα από τα generators (comprehensions).

 

Στο ίδιο ακριβώς πνεύμα κινούνται και τα υπόλοιπα παραδείγματα που έδωσα. Και το "κανένα από τα δυο" προφανώς δεν είναι σοβαρή απάντηση στην ερώτηση "ποιο από τα 2 είναι more pythonic way". Υπενθυμίζω πως το more το εισήγαγες εσύ στην κουβέντα.

 

Επίσης το Zen of Python από ότι έχω καταλάβει έχει ήδη υποστεί μια προσθήκη, αλλά παρόλα αυτά παραμένει too generic (and too cryptic, if you ask me). To PEP8 παρουσιάζει το coding-style που χρησιμοποιεί η στάνταρ βιβλιοθήκη της γλώσσας, αλλά κάνει σαφές από πολύ νωρίς (στην Εισαγωγή του) πως...

 

...

Many projects have their own coding style guidelines. In the event of any conflicts, such project-specific guides take precedence for that project.

...

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

 

Εν ολίγοις, σε τέτοιες γλώσσες, που είναι συνειδητά και έτσι και γιουβέτσι και κοκορέτσι (δεν το λέω υποτιμητικά, ίσα-ίσα) τα πάντα ρει και μάλιστα περισσότερο από ότι "ρει" σε πιο restrictve γλώσσες (γιατλι κι εκεί "ρει" αλλά ας μην το αναλύσουμε και αυτό :P)!

 

Παρ' όλα αυτά ποτέ δεν είπα (ούτε και κανένας άλλος νομίζω) ότι there is only one way. Απλά υπάρχουν λύσεις που είναι πιο pythonic από κάποιες άλλες απ' την άποψη ότι εκμεταλλεύονται τις ιδίοτητες/σύνταξη/built-in funcs/built-in types της γλώσσας και καταλήγουν σε πιο simple, readable και elegant κώδικα. Μπορεί αυτές οι λύσεις να είναι παραπάνω από μία, αλλά ΔΕΝ είναι όλες οι λύσεις pythonic!

Οπότε, ποιος από τους παραπάνω τρόπους για τύπωμα list items ένα σε κάθε γραμμή είναι πιο pythonic, ποιοι δεν είναι pythonic, με ποια κριτήρια κάποιοι θεωρούνται simple, readable, elegeant (εγώ νομίζω πως εδώ πραγματικά θα δυσκολευτείς να συνδυάσεις ή/και να κάνεις rule out κάποιο/κάποια από αυτά τα χαρακτηριστικά), ποιοι εκμεταλλεύονται περισσότερο ή λιγότερο τις ιδίοτητες/σύνταξη/built-in funcs/built-in types της γλώσσας (κι εδώ θα δυσκολευτείς πιστεύω, ιδίως να χρησιμοποιήσεις ως κριτήριο που θα σε οδηγήσουν ως συμπέρασμα στα προηγούμενα χαρακτηριστικά).

 

Σχετικά με το config που λες δεν νομίζω ότι τίθεται θέμα pythonic way γιατί στην κάθε περίπτωση το αποτέλεσμα είναι διαφορετικό. Όπως είπες με άλλον έχεις απευθείας access, αλλού δημιουργείς objects κλπ. Στα παραπάνω παραδείγματα δεν βρίσκω κανέναν λόγο να μην χρησιμοποιήσεις τον "pythonic way" παίρνοντας ακριβώς το ίδιο αποτέλεσμα. Αφού πάντα θα έχεις λιγότερο και πιο clean κώδικα.

Όχι δεν είναι όλα διαφορετικά. Π.χ. το 2ο και το 3ο παράδειγμα νομίζω (δλδ δεν είμαι 100% σίγουρος αυτή τη στιγμή) πως μπορείς να τα χρησιμοποιήσεις πανομοιότυπα:

 

from config.py import GuiStrings

cfg = GuiStrings()
if ( cfg.s1 == '1' ):
    ...
Δεν είναι όμως αυτό το main point μου! Το config.py διάβασα πως είναι ο συνηθισμένος τρόπος για να ορίζουμε το γενικό configuration των προγράμματών μας. Και πως παλαιότερα η συνηθισμένη πρακτική ήταν λέει να αραδιάζουμε τα πάντα χύμα μέσα. Πολλές όμως βιβλιοθήκες, προτζεκτς, κλπ, χρησιμοποιούν κλάσεις, άλλες χρησιμοποιούν και instantiatable κλάσεις, κλπ.

 

Ποιος από όλους τους τρόπους αυτούς είναι more pythonic και κυρίως γιατί. Προφανώς δεν είμαι ούτε ο πρώτος ούτε ο μόνος που έχει τέτοιου είδους ανησυχίες. Π.χ. να κι ένας άλλος (αν κι αυτός το πάει ακόμα παραπέρα, δεν ρωτάει απλά για more αλλά για most pythonic way :P): http://stackoverflow.com/questions/6198372/most-pythonic-way-to-provide-global-configuration-variables-in-config-py

 

Όπως ήταν αναμενόμενο (για μένα τουλάχιστον) αντί για απαντήσεις που να συγκλίνουν σε έναν τρόπο (είτε more" είτε "most" pythonic) πήρε ως απάντηση 5-6 άλλους διαφορετικούς τρόπους, που λίγο πολύ παρουσιάστηκαν ως ισοδύναμοι, ή με άλλα λόγια πως δεν υπάρχει κάποιος "more" ή "most" pythonic (ή τουλάχιστον αυτό εισέπραξα εγώ).

 

Δεν μίλησα για ισότητα, αλλά για το αν αποτελούνται ακριβώς απ' τους ίδιους χαρακτήρες. Δηλαδή το f("abcD", cDDbaa") να δίνει True, ενώ το f("abc", "cbaf") να δίνει False.

Α οκ! (δεν το είχα πιάσει )

 

 

Δημοσ.

@migf1

 

 

Δεν δίνεις αρκετές πληροφορίες για την επιλογή του configuration. Η βέλτιστη επιλογή εξαρτάται από πολλούς παράγοντες. Σε μία εφαρμογή που θα μοιράσεις σε άλλους συνήθως δεν θέλεις το config αρχείο να είναι *.py γιατί δίνεις την δυνατότητα σε κάποιον να εκτελέσει arbitrary κώδικα. Για απλά αρχεία ini υπάρχει στην Standard Library το ConfigParser το οποίο δουλεύει αρκετά καλά αν δεν έχεις άπειρες απαιτήσεις (για python 2.7- μάλλον θέλεις να χρησιμοποιήσεις το backport από την 3). Αν θέλεις πιο πολλές δυνατότητες (πχ Validation) θα πρέπει να πας σε 3rd party library όπως η ConfigObj. Αν θέλεις να είναι human readable το αρχείο, συχνά προτείνεται η χρήση του YAML αλλά το PyYaml δεν είναι στην Standard Library το οποίο μπορεί να είναι πρόβλημα σε κάποιες περιπτώσεις.

 

Από αυτά που προτείνεις εγώ θα προτιμούσα είτε απευθείας το module είτε μία κλάση σαν την Global (με διαφορετικό όνομα μάλλον). Οι διαφορές τους δεν είναι και τόσο μεγάλες καθώς και τα δύο κατ' ουσίαν είναι namespaces. Αν πας σε κλάσεις νομίζω ότι ένα Borg (ή «stateless proxy») είναι αρκετά βολικό/χρήσιμο αλλά δεν ξέρω πως δουλεύει αν έχεις πολλά threads (μάλλον δεν έχει και τόση σημασία αν δεν κάνεις αλλαγές στο configuration μέσα στο πρόγραμμά σου).

 

 

  • Like 1
Δημοσ.

@pmav99:

 

 

Αδερφέ pmav99 σε ευχαριστώ πολύ! Αφενός για τις πληροφορίες που μου δίνεις, κι αφετέρου επειδή δεν κολλάς σε pythonic και μη pythonic ways (όχι μόνο εδώ, αλλά σε όλες τις περιπτώσεις που έχει τύχει να συναντηθούμε περί Python). Και κυρίως επειδή οι πληροφορίες και τα links που μου δίνεις γενικώς, με έχουν γλιτώσει από αρκετή ταλαιπωρία και ψάξιμο.

 

 

 

@pmav99:

 

 

Θέλω να ρωτήσω κάτι σχετικά με το config.py, αλλά για να μη διαλύουμε άλλο το νήμα του φίλου gon, πάω στο νήμα της python. Όταν βρεις χρόνο και διάθεση, ρίξε μια ματιά... πάω να γράψω την ερώτηση εκεί.

 

 

Δημοσ.

@migf1

 

Σόρι, αλλά εσύ εδώ αλλοίωσες το παράδειγμα. Εγώ αυτό που εννοούσα ήταν ποιος από τους 2 τρόπους (και κυρίως γιατί) είναι "more pythonic" για να τυπώσεις τα περιεχόμενα μιας λίστας (κι εσύ μου απαντάς πως το πιο pythonic είναι να τυπώνεις 5 ακέραιους)

 

Με συγχωρείς δεν το κατάλαβα. Με μπέρδεψες γιατί στο 2ο χρησιμοποιείς χωρίς κανέναν απολύτως λόγο την enumerate() (με την ίδια λογική θα μπορούσες να χρησιμοποιήσεις 2 φορές την reversed ξέρω 'γω, λολ). Στα υπόλοιπα one-liners, χρησιμοποιείς επίσης συναρτήσεις ή μεθόδους όπως τη map και τη join μαζί με το loop οπότε ο κώδικας γίνεται λιγότερο απλός και αναγνώσιμος. Οπότε ναι, το for i in _list: print(i) είναι ο πιο pythonic τρόπος για να εκτυπώσεις τα στοιχεία μιας λίστας. Τώρα μη μου ζητήσεις να στα συγκρίνω τα υπόλοιπα one-liners μεταξύ τους. :P


Αυτό με το list comprehesion θα το απέφευγα και για παραπάνω λόγους: http://stackoverflow.com/questions/8695488/proper-use-of-list-comprehensions-python


 

Πάλι μου απαντάς αλλοιώνοντας το παράδειγμα. Εγώ θέλω να τυπώσω τα περιεχόμενα μιας υπάρχουσας λίστας. Εσύ εδώ του βάζεις και αύξοντα αριθμό μπροστά.

Δεν αλλοίωσα κάτι εδώ, απλά δείχνω πως μπορεί να γραφεί more pythonic το συγκεκριμένο snippet (άσχετα με το παράδειγμα σου που ακόμα δεν κατάλαβα γιατί έβαλες enumerate).
 

 

Και το "κανένα από τα δυο" προφανώς δεν είναι σοβαρή απάντηση στην ερώτηση "ποιο από τα 2 είναι more pythonic way". Υπενθυμίζω πως το more το εισήγαγες εσύ στην κουβέντα.

 

Δεν είπα όμως ποτέ ότι σε δύο λύσεις πάντα η μία απ' τις δύο είναι περισσότερο pythonic. Είπα γενικά ότι υπάρχουν λύσεις που είναι πιο pythonic από άλλες και έδωσα και συγκεκριμένα παραδείγματα.

 

Οπότε, ποιος από τους παραπάνω τρόπους για τύπωμα list items ένα σε κάθε γραμμή είναι πιο pythonic, ποιοι δεν είναι pythonic, με ποια κριτήρια κάποιοι θεωρούνται simple, readable, elegeant (εγώ νομίζω πως εδώ πραγματικά θα δυσκολευτείς να συνδυάσεις ή/και να κάνεις rule out κάποιο/κάποια από αυτά τα χαρακτηριστικά), ποιοι εκμεταλλεύονται περισσότερο ή λιγότερο τις ιδίοτητες/σύνταξη/built-in funcs/built-in types της γλώσσας (κι εδώ θα δυσκολευτείς πιστεύω, ιδίως να χρησιμοποιήσεις ως κριτήριο που θα σε οδηγήσουν ως συμπέρασμα στα προηγούμενα χαρακτηριστικά).

 


Simple is better than complex.
Το γιατί είναι πιο simple το πρώτο, πρώτο που πόσταρες νομίζω είναι προφανές. Τα υπόλοιπα one-liners δεν θα έλεγα ότι εκμεταλλεύονται κάποιο χαρακτηριστικό της γλώσσας, αντιθέτως κάνουν abuse.
 

 

Σχετικά με τα config.py δεν το χω ψάξει καθόλου και δεν μπορώ να σου απαντήσω κάτι.
 

Όπως ήταν αναμενόμενο (για μένα τουλάχιστον) αντί για απαντήσεις που να συγκλίνουν σε έναν τρόπο (είτε more" είτε "most" pythonic) πήρε ως απάντηση 5-6 άλλους διαφορετικούς τρόπους, που λίγο πολύ παρουσιάστηκαν ως ισοδύναμοι, ή με άλλα λόγια πως δεν υπάρχει κάποιος "more" ή "most" pythonic (ή τουλάχιστον αυτό εισέπραξα εγώ).

 


Κοίτα, δεν είπα ποτέ ότι κάθε γραμμή κώδικα που γράφουμε σε python πρέπει να καθόμαστε και να αναρωτιόμαστε με τις ώρες αν είναι ότι πιο "pythonic" υπάρχει. Κάτι τέτοιο θα ήταν άρρωστο.

Αντίθετα είπα ότι πολλά πράγματα (και έδωσα και συγκεκριμένα παραδείγματα όπως με την f function που έγραψα παραπάνω και με το πιο πάνω snippet με την enumerate τα οποία απέφυγες να σχολιάσεις) μπορούν να γραφτούν με «καλύτερο» τρόπο στην συγκεκριμένη γλώσσα και ίσως αυτός ο τρόπος είναι και language-specific. Εσύ απ' την άλλη με ρωτάς ποιο από δύο ή περισσότερα συγκεκριμένα snippets που σκέφτηκες είναι πιο pythonic. Ξαναλέω λοιπόν δεν είναι πάντα η μία λύση περισσότερο pythonic απ' την άλλη.

PS1.
Μπορώ να δώσω περισσότερα παραδείγματα αν ακόμα δεν έπιασες το point μου.

PS2.
Για να μην παρεξηγηθώ και επειδή γενικά σέβομαι πολύ τις απόψεις σου, ούτε python fanboy είμαι, ούτε σε καμία περίπτωση προσπαθώ να στην πω. Καταλαβαίνω μέχρι ενός σημείου την άποψη σου αλλά μου φάνηκες πολύ απόλυτος σε προηγούμενα ποστ.

PS3.
Με έκανες και μένα να σιχαθώ τον όρο pythonic... :P

 

 

 

Δημοσ.

@ilias:

 

 

Ηλία κατ' αρχήν ευχαριστώ για τα καλά σου λόγια. Ο σεβασμός είναι αμοιβαίος, και μάλιστα από πολύ νωρίς, από το φόρουμ του ubuntu.gr.

 

Προφανώς και καταλαβαίνω τι εννοείς. Τα γράφω και στο άλλο νήμα (που μόλις ποστάρισα) περί τη χρησιμότητα των guidelines. Ειδικά σε multi-paradigm γλώσσες (προσθέτω εδώ). Εκεί που τσινάω είναι στα δήθεν "πρέπει" (προφανώς δεν αναφέρομαι σε σένα προσωπικά).

 

Επίσης προφανώς, μια απλή και readable υλοποίηση είναι αυτονόητα προτιμητέα έναντι π.χ. μιας με spaghetti code. Η ένστασή μου στα διάφορα "way"s είναι βαθύτερη κι ευρύτερη από απλά onliners και παραδείγματα. Π.χ. αν είμαι έμπειρος κι αισθάνομαι πως θα κάνω τη δουλειά μου καλύτερα imperatively, δεν θα μου επιβάλει το οποιοδήποτε guideline να την κάνω π.χ. functionally.. και το αντίστροφο.

 

Αν το "XXX way" της όποιας γλώσσας είναι κάποιο συγκεκριμένο (καλά αυτό είπαμε δεν υπάρχει στις multi-paradigm γλώσσες... ή μάλλον υπάρχει αλλά κατά τη δική μου άποψη είναι απλά για να γελάμε) τότε γιατί αυτή η γλώσσα υποστηρίζει κι άλλα 100 ways? Π.χ. η Java σου λέει, ξέρεις κάτι φίλε ακόμα κι ένα "hello world" να θέλεις να γράψεις, θα φτιάξεις κλάση... σου αρέσει δεν σου αρέσει. Θες πολλές κλάσεις; μάλιστα, η κάθε μια σε ξεχωριστό αρχείο, σου αρέσει δεν σου αρέσει. Θες multiple inhertiance? Μάλιστα, ή κάντο με composition ή/και με interfaces κι αν δεν σου αρέσει άλλαξε γλώσσα.

 

Δεν σου δίνει 1000000 features, paradigms, κλπ και να βγαίνουν μετά στα φόρουμ και στα blogs, ενίοτε και στα βιβλία, "ειδικοί" για να σου λένε α όχι φίλε, αυτό που λέμε εμείς είναι το "Java way"... σαν να σου λένε δηλαδή πως όλα τα υπόλοιπα που υποστηρίζει συνειδητά η γλώσσα είναι για τα μπάζα ή δεν ξέρω 'γω τι.

 

ΥΓ. Περί Python ας πάμε στο άλλο νήμα καλύτερα. Το έχουμε σκίσει το νήμα του gon

 

 

Δημιουργήστε ένα λογαριασμό ή συνδεθείτε για να σχολιάσετε

Πρέπει να είστε μέλος για να αφήσετε σχόλιο

Δημιουργία λογαριασμού

Εγγραφείτε με νέο λογαριασμό στην κοινότητα μας. Είναι πανεύκολο!

Δημιουργία νέου λογαριασμού

Σύνδεση

Έχετε ήδη λογαριασμό; Συνδεθείτε εδώ.

Συνδεθείτε τώρα
  • Δημιουργία νέου...