Διάλεξη 23ης Νοεμβρίου 2016
Ακολουθίες. Μέθοδοι για ακολουθίες χαρακτήρων. Μορφοποίηση εξόδου
Έχουμε δει τέσσερις τύπους ακολουθιών: τις ακολουθίες χαρακτήρων (strings), τις πλειάδες (tuples), τις λίστες (lists)
και τον τύπο range. Μια σταθερά τύπου string ορίζεται αναγράφοντας τους χαρακτήρες από τους οποίους αποτελείται μεταξύ
μονών ή διπλών εισαγωγικών, όπως 'lemon'
ή "orange"
. Οι λίστες κατασκευάζονται αναγράφοντας τα
στοιχεία τους ανάμεσα σε αγκύλες, χωρισμένα με κόμματα: ['a', 2, 'cee', [3, 4]]
. Τα στοιχεία μιας λίστας δεν
είναι απαραίτητο να έχουν όλα τον ίδιο τύπο. Μια πλειάδα ορίζεται αναγράφοντας τα στοιχεία της μεταξύ παρενθέσεων. Η κενή
πλειάδα γράφεται ως ()
ενώ η πλειάδα με μοναδικό στοιχείο τον χαρακτήρα 'a' γράφεται ως ('a',)
.
Μια ακολουθία τύπου range
γράφεται στη μορφή range([start], stop[,step])
και αναφέρεται στην
ακολουθία με όρους τους ακέραιους start, start + step, start + 2*step,...
. Αν το όρισμα step
είναι θετικός αριθμός
ο τελευταίος όρος της ακολουθίας είναι ο μεγαλύτερος ακέραιος της μορφής
start + i*step
ο οποίος είναι αυστηρά μικρότερος του stop
. Αν το όρισμα step
είναι
αρνητικός αριθμός ο τελευταίος όρος της ακολουθίας είναι το μικρότερο στοιχείο της μορφής
start + i*step
το οποίο είναι μεγαλύτερο από το stop
. Όπως μαρτυρά και το συντακτικό της,
μόνο το όρισμα stop
είναι υποχρεωτικό. Μπορούμε να μετατρέψουμε ένα αντικείμενο τύπου range
σε λίστα
χρησιμοποιώντας τη σύναρτηση list()
.
>>> list(range(1,10,2))
[1, 3, 5, 7, 9]
>>> list(range(10,2,-1))
[10, 9, 8, 7, 6, 5, 4, 3]
>>> list(range(10))
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> list(range(1,0))
[]
Όλοι οι τύποι ακολουθιών υποστηρίζουν τις ακόλουθες λειτουργίες (s, t είναι ακολουθίες, n, i, j, k είναι ακέραιοι):
x in s
: είναιTrue
αν το x είναι στοιχείο της ακολουθίας s, διαφορετικά είναιFalse
.x not in s
: είναιTrue
αν το x δεν είναι στοιχείο της ακολουθίας s, διαφορετικά είναιFalse
.s+t
: η συνένωση των ακολουθιών s και t.s * n
ήn * s
: συνένωση n αντιγράφων της ακολουθίας s.s[i]
: το i-οστό στοιχείο της ακολουθίας s.s[i:j]
: τα στοιχεία της s από τις θέσεις i ως j.s[i:j:k]
: τα στοιχεία της s από τις θέσεις i ως j με βήμα k.len(s)
: ο αριθμός των στοιχείων της ακολουθίας s.min(s)
: το ελάχιστο στοιχείο της ακολουθίας s.max(s)
: το μέγιστο στοιχείο της ακολουθίας s.s.index(e)
: η θέση της πρώτης εμφάνισης του στοιχείου e στην ακολουθία s.s.count(e)
: αριθμός εμφανίσεων του στοιχείου e στην ακολουθία s.
Αναφερόμαστε στις λειτουργίες index
και count
ως μεθόδους και στρέφουμε την προσοχή τπυ
αναγνώστη στο συντακτικό τους, το οποίο είναι τυπικό όλων των μεθόδων για όλους τους τύπους ακολουθιών. Αναφέρουμε παρακάτω
μερικές από τις δεκάδες μεθόδους που η υποστηρίζει η Python για τις ακολουθίες χαρακτήρων. Σε ότι ακολουθεί, s
είναι μια ακολουθία χαρακρήρων.
s.capitalize()
: επιστρέφει ένα αντίγραφο του s όπου ο πρώτος χαρακτήρας, αν είναι γράμμα, έχει γίνει
κεφαλαίο γράμμα.
>>> s = 'maria'
>>> s.capitalize()
'Maria'
>>> 'john'.capitalize()
'John'
>>> '123'.capitalize()
'123'
s.center(width [,fillchar])
: επιστρέφει ένα αντίγραφο του s στο κέντρο μιας ακολουθίας
χαρακτήρων μήκους width με τους περιβάλλοντες χαρακτήρες ίσους με το fillchar, αν δίνεται,
διαφορετικά κενούς χαρακτήρες. Οι μέθοδοι s.ljust(width [,fillchar])
και
s.rjust(width [,fillchar])
επιτελούν παρόμοιες λειτουργίες.
>>> s = 'python'
>>> s.center(12)
' python '
>>> s.center(12, '-')
'---python---'
>>> s.ljust(12, '-')
'python------'
>>> s.rjust(12, '*')
'******python'
s.endswith(suffix[, start[, end]])
: επιστρέφει True αν η ακολουθία s καταλήγει
με τους χαρακτήρες suffix, διαφορετικά False. Τα προαιρετικά ορίσματα start και
stop περιορίζουν το εύρος της αναζήτησης της κατάληξης suffix. Η μέθοδος
s.startswith(prefix[, start[, end]])
επιτελεί παρόμοια λειτουργία.
>>> s = 'really long string'
>>> s.endswith('ing')
True
>>> s.endswith('str', 10, 15)
True
>>> 'Manchester by the sea'.startswith('che')
False
s.find(sub[, start[, end]])
: επιστρέφει τον δείκτη της πρώτης εμφάνισης του string sub στην
ακολουθία s, διαφορετικά -1. Τα προαιρετικά ορίσματα start και end περιορίζουν
το εύρος της αναζήτησης στο κομμάτι s[start:end]
. Η μέθοδος s.rfind(sub[, start[, end]])
επιστρέφει τον δείκτη της τελευταίας εμφάνισης του string sub στην ακολουθία s
>>> s = 'needle in a haystack'
>>> s.find('hay')
12
>>> s.find('needle', 5)
-1
>>> 'Mississippi'.rfind('ssi')
5
s.join(seq)
: επιστρέφει μια ακολουθία χαρακτήρων αποτελούμενη από την συνένωση των στοιχείων της ακολουθίας seq.
Τα στοιχεία της ακολουθίας ενώνονται με την ακολουθία s.
>>> ' '.join('maria')
'm a r i a'
>>> '-'.join(['python', 'is', 'fun'])
'python-is-fun'
s.split([sep[, maxsplit]])
: επιστρέφει μια λίστα αποτελούμενη από τα μέρη στα οποία χωρίζει την ακολουθία
χαρακτήρων s το sep. Αν ο ακέραιος maxsplit δίνεται τότε επιστρέφονται ακριβώς
maxsplit+1
στοιχεία. Η μέθοδος s.rsplit([sep[, maxsplit]])
χωρίζει την ακολουθία s
ξεκινώντας από δεξιά.
>>> s = 'four score and sever years ago'
>>> s.split(' ')
['four', 'score', 'and', 'sever', 'years', 'ago']
>>> s.split(' ', 2)
['four', 'score', 'and sever years ago']
s.splitlines([keepends])
: επιστρέφει μια λίστα αποτελούμενη από τις γραμμές της ακολουθίας χαρακτήρων
s. O χαρακτήρας '\n δεν συμπεριλαμβάνεται εκτός και αν το όρισμα keepends δίνεται και
είναι ίσο με True.
>>> s = 'It was the best of times.\nIt was the worst of times.\nIt was the age of wisdom.\nIt was the age of foolishness.\n'
>>> s.splitlines()
['It was the best of times.', 'It was the worst of times.', 'It was the age of wisdom.', 'It was the age of foolishness.']
>>> s.splitlines(True)
['It was the best of times.\n', 'It was the worst of times.\n', 'It was the age of wisdom.\n', 'It was the age of foolishness.\n']
s.partition(sep)
: επιστρέφει μια πλειάδα με τρία στοιχεία, το μέρος του s πρίν την πρώτη εμφάνιση
της ακολουθίας sep,
την ίδια την ακολουθία sep και το μέρος του s μετά την ακολουθία sep. Η μέθοδος
s.rpartition(sep)
επιτελεί παρόμοια λειτουργία, χωρίζοντας όμως με βάση την τελευταία εμφάνιση της
ακολουθίας sep.
>>> 'www.tem.uoc.gr'.partition('.')
('www', '.', 'tem.uoc.gr')
>>> 'www.tem.uoc.gr'.rpartition('.')
('www.tem.uoc', '.', 'gr')
>>> 'www.tem.uoc.gr'.partition(',')
('www.tem.uoc.gr', '', '')
s.replace(old, new[, count])
: αντικαθιστά κάθε εμφάνιση του old με το new. Αν το προαιρετικό
όρισμα count δίνεται τότε οι αντικαταστάσεις εκτελούνται το πολύ count φορές.
>>> s = 'My number is 2810-39-3709'
>>> s.replace('-', '.')
'My number is 2810.39.3709'
s.strip([chars])
: αφαιρεί τους χαρακτήρες chars από την αρχή και το τέλος της ακολουθίας χαρακτήρων
s. Αν η ακολουθία chars δεν δίνεται αφαιρούνται οι κενοί χαρακτήρες. Οι μέθοδοι
s.lstrip([chars])
και s.rstrip([chars])
αφαιρούν τους χαρακτήρες chars από την αρχή,
αντίστοιχα από το τέλος της ακολουθίας s.
>>> s = 'A lot of spaces, left and right '
>>> s.strip()
'A lot of spaces, left and right'
>>> 'madam'.lstrip('m')
'adam'
>>> 'madam'.rstrip('am')
'mad'
Ο ενδιαφερόμενος αναγνώστης καλείται να αναζητήσει περισσότερες πληροφορίες για τις παραπάνω μεθόδους, γράφοντας,
για παράδειγμα, help(sṫr.find)
στη γραμμή εντολών της Python, όσο και για τις μεθόδους
s.isalnum()
, s.isalpha()
, s.isdecimal()
, s.isdigit()
,
s.isidentifier()
, s.islower()
, s.isnumeric()
, s.isprintable()
,
s.isspace()
, s.isupper()
, s.lower()
, s.upper()
,
s.zfill(width)
και s.swapcase()
τις οποίες δεν θα συζητήσουμε εδώ.
Μορφοποίηση εξόδου
Η Python3 παρέχει τη μέθοδο s.format()
η οποία μορφοποιεί τα ορίσματά της σύμφωνα με τις οδηγίες
που αναγράφονται στην ακολουθία χαρακτήρων s και επιστρέφει μια καινούργια ακολουθία χαρακτήρων η οποία
περιέχει τη ζητούμενη κωδικοποίηση. Εξηγούμε και παραθέτουμε παραδείγματα.
΄Έστω ότι θέλουμε να φτιάξουμε τον πίνακα τιμών των συναρτήσεων $x^2$ και $x^4$ για τους πρώτους 20 φυσικούς αριθμούς. Μπορούμε, φυσικά, να γράψουμε
for i in range(1,21):
print(i, i**2, i**4)
και να πάρουμε το αποτέλεσμα
1 1 1
2 4 16
3 9 81
4 16 256
5 25 625
6 36 1296
7 49 2401
8 64 4096
9 81 6561
10 100 10000
11 121 14641
12 144 20736
13 169 28561
14 196 38416
15 225 50625
16 256 65536
17 289 83521
18 324 104976
19 361 130321
20 400 160000
Το μόνο πρόβλημα στον παραπάνω πίνακα είναι η στοίχιση των αριθμών. Προφανώς θα παίρναμε ένα αισθητικά καλύτερο αποτέλεσμα αν στοιχίζαμε την πρώτη στήλη σε ένα πλάτος πεδίου 2, τη δεύτερη στήλη σε ένα πλάτος πεδίου 3 και την τελευταία στήλη σε ένα πλάτος πεδίου 6. Ένας τρόπος να δώσουμε αυτές τις οδηγίες μορφοποίησης στην Python είναι ο παρακάτω:
for i in range(1,21):
print('{:2d}\t{:3d}\t:{:6d}'.format(i, i**2, i**4)
Το αποτέλεσμα αυτής της μορφοποίησης είναι
1 1 1
2 4 16
3 9 81
4 16 256
5 25 625
6 36 1296
7 49 2401
8 64 4096
9 81 6561
10 100 10000
11 121 14641
12 144 20736
13 169 28561
14 196 38416
15 225 50625
16 256 65536
17 289 83521
18 324 104976
19 361 130321
20 400 160000
το οποίο είναι, αισθητικά τουλάχιστο, πιο ευχάριστο από τον προηγούμενο πίνακα. Ας δούμε τις λεπτομέρειες της μορφοποίησης: κατ' αρχήν
τα ορίσματα της μεθόδου format
είναι οι προς μορφοποίηση αριθμοί. Οι κωδικοί μορφοποίησης αναγράφονται, μέσα σε άγκιστρα, στην ακολουθία
χαρακτήρων που προηγείται της μεθόδου. Ο πρώτος κωδικός μορφοποίησης αντιστοιχεί στο πρώτο όρισμα της format
κλπ.
Ο πρώτος κωδικός μορφοποίησης είναι ο {:2d}
ο οποίος, εναλλακτικά, μπορεί να γραφεί και ως {0:2d}
, με το ψηφίο μηδέν
να αναφέρεται στον αριθμό του ορίσματος προς μορφοποίηση (θυμόμαστε ότι η Python αριθμεί ξεκινώντας από το μηδέν). Μεταξύ των κωδικών μορφοποίησης
υπάρχει ο χαρακτήρας εσοχή (tab) '\t'
απλά και μόνο για να αφήσει ένα αριθμό από κενούς χαρακτήρες μεταξύ των στοιχείων που εκτυπώνονται.
Ο κώδικας 2d
αποτελείται από ένα αριθμό, το πλάτος του πεδίου στο οποίο θα τυπωθεί το προς μορφοιποίηση στοιχείο και τον χαρακτήρα d
ο οποίος δηλώνει τον τρόπο αναπαράστασης του στοιχείου που μορφοποιείται. Ο χαρακτήρας d αφορά στους ακέροιους αριθμούς στο δεκαδικό σύστημα
(decimal integers). Άλλοι κωδικοί, κατάλληλοι για ακεραίους είναι οι b για εκτύπωση στο δυαδικό σύστημα (binary system), o για εκτύπωση
στο οκταδικό σύστημα (octal), x ή X για εκτύπωση στο δεκαεξαδικό σύστημα (hexadecimal) και n για εκτύπωση πάλι στο
δεκαδικό σύστημα αλλά με εμφανή τον χαρακτήρα για το διαχωρισμό χιλιάδων. Ως παράδειγμα, εκτυπώνουμε τους αριθμούς από το 32 ως το 49 στο δεκαδικό,
οκταδικό, δεκαεξαδικό και δυαδικό σύστημα χρησιμοποιώντας τη μορφοποίηση '{:2d}\t{:2o}\t{:2x}\t{:7b}'
. Μπορούμε, βεβαίως, να παραλέιψουμε
το πλάτος του πεδίου και να γράψουμε, για παράδειγμα, {:d}
. Σε αυτή την περίπτωση θα επιλεγεί, για κάθε αριθμό προς μορφοποίηση το κατάλληλο
πλάτος πεδίου.
32 40 20 100000
33 41 21 100001
34 42 22 100010
35 43 23 100011
36 44 24 100100
37 45 25 100101
38 46 26 100110
39 47 27 100111
40 50 28 101000
41 51 29 101001
42 52 2a 101010
43 53 2b 101011
44 54 2c 101100
45 55 2d 101101
46 56 2e 101110
47 57 2f 101111
48 60 30 110000
49 61 31 110001
Για τους πραγματικούς αριθμούς, ακριβέστερα για τους αριθμούς κινητής υποδιαστολής (floating point numbers) η Python παρέχει τους
κωδικούς μορφοποίησης e, E, f, D, g, G, n και %. Οι λεπτομέρεις έχουν ως εξής: οι κωδικοί f, F
εκτυπώνουν 6 δεκαδικά ψηφία μετά την υποδιαστολή, σε ένα πλάτος πεδίου ανάλογο με μέγεθος του αριθμού που τυπώνεται. Το πλάτος
πεδίου και ο αριθμός των δεκαδικών ψηφίων μετά την υποδιαστολή μπορεί να δοθεί πριν τον κωδικό f όπως στην
περίπτωση {:8.5f}
, όπου χρησιμοποιείται ένα πλάτος πεδίου 8 και 5 δεκαδικά ψηφία. Για παράδειγμα,
οι εντολές
for i in range(1,13): print('{:2d}--{:f}--{:6.3f}'.format(i, 1/i, 1/i))
θα εκτυπώσουν
1--1.000000-- 1.000
2--0.500000-- 0.500
3--0.333333-- 0.333
4--0.250000-- 0.250
5--0.200000-- 0.200
6--0.166667-- 0.167
7--0.142857-- 0.143
8--0.125000-- 0.125
9--0.111111-- 0.111
10--0.100000-- 0.100
11--0.090909-- 0.091
12--0.083333-- 0.083
Οι κωδικοί e, E εκτυπώνουν τα αντίστοιχα ορίσματα χρησιμοποοιώντας τον επιστημονικό συμβολισμό. Είναι δυνατόν να καθορίσουμε
τόσο το πλάτος πεδίου όσο και τον αριθμό των δεκαδικών ψηφίων. Αν αυτός δεν δοθεί τότε τυπώνονται 12 δεκαδικά ψηφία μετά την υποδιαστολή.
Για παράδειγμα, χρησιμοποιώντας τον κωδικό μορφοποίησης {:15.8e}
για να εκτυπώσουμε τους αριθμούς $\sin 1, \sin 2,\ldots, \sin 12$,
λαμβάνουμε:
8.41470985e-01
9.09297427e-01
1.41120008e-01
-7.56802495e-01
-9.58924275e-01
-2.79415498e-01
6.56986599e-01
9.89358247e-01
4.12118485e-01
-5.44021111e-01
-9.99990207e-01
-5.36572918e-01
Ο κωδικός %
πολλαπλασιάζει το αντίστοιχο όρισμα με το 100 εκτυπώνει χρησιμοποιώντας τον κωδικό μορφοποίησης f
ακολουθούμενο
από το σύμβολο %. Οι κωδικοί g, G
μοροφοποιούν το αντίστοιχο όρισμα είτε όπως ο κωδικός f
είτε όπως ο κωδικός e
,
ανάλογα με το μέγεθός του. Ο κωδικός μορφοποίησης n
είναι ανάλογος αλλά εκτυπώνει, επιπλέον, το σύμβολο διαχωρισμού των χιλιάδων.
Τέλος, για τις ακολουθίες χαρακτήρων μπορούμε να χρησιμοποιήσουμε τους κωδικούς μορφοποίησης {:<w}, {:>w}, {:^p}
για να
εκτυπώσουμε το αντίστοιο όρισμα σε ένα πλάτος πεδίου w, στοιχισμένο αριστερά, δεξιά ή στη μέση, αντίστοιχα.
for i in range(1,10): print('{0:>{width}}'.format('*', width = i)
*
*
*
*
*
*
*
*
*
Δείτε και το πρόγραμμα για τον πίνακα της προαπαίδειας.