rangkuman buku Python Data Structures and Algorithms chapter 1

Objek, Jenis, dan Ekspresi Python


       Python adalah salah satu bahasa pemrograman tingkat lanjut yang termudah bagi pemula. python juga merupakan bahasa pilihan untuk banyak tugas data tingkat lanjut karena alasan yang sangat bagus. Di python, ada banyak struktur data dan algoritma yang baerguna yang dibangun ke dalam bahasa tersebut.

        Selain itu, karena Python adalah bahasa berbasis objek, membuat objek data khusus relatif mudah. Namun, jika kamu sedikit tidak paham, berasal dari bahasa lain, atau tidak memiliki pengetahuan sama sekali tentang python, jangan kwhawatir, bab pertama ini akan segera menjelaskannya kepada kamu.

Memahami struktur data dan algoritma 

algoritma dan struktur data adalah konsep paling dasar dalam ilmu komputer. Memiliki pemahaman tentang konsep dasar ini sangat penting dalam desain perangkat lunak dan melibatkan tiga karakteristik berikut :

Bagaimana algoritma memanipulasi informasi yang terkandung dalam struktur data?

bagaimana data diatur dalam memori?

apa karakteristik dari sturktur data tertentu?

Pertama-tama kita akan melihat dasar-dasar bahasa pemrograman python dalam hal struktur data algoritma. Kedua, penting bagi kamu untuk memiliki alat matematika yang tepat. kita perlu memahami beberapa konsep dasa ilmu komputer dan untuk itu kamu membutuhkan matematika. Mengambil pendekatan intuitif berarti kita tidak memerlukan lebih dari matematika sekolah menengah untuk mengembangkan beberapa prinsip paduan umumnya untuk memahami prinsip dari ide inti ini. 

Akhirnya, kita membutuhkan strategi desain eksperimental yang solid. Untuk memberi kita beberapa wawasan tentang pemikiran algoritmik, mari kita ambil contoh dunia nyata. Bayangkan kita berada di pasar yang tidak diketahui dan diberi tugas untuk membeli daftar produk. Tujuan kami adalah meminimalkan harga yang kami bayarkan untuk setiap prosuk serta meminimalkan waktu yang dihabiskan di pasar. salah satu cara untuk mendekati ini adalah dengan menulis algoritma seperti berkut:

ulangi untuk setiap vendor :

  1. Apakah vendor memiliki item di daftar saya dan biayanya kurang dari perkiraan biaya untuk barang?
  2. Jika ya, beli dan hapus dari daftar; jika tidak, lanjutkan ke vendor berikutnya. 
  3. Jika tidak ada lagi vendor, akhiri.
Jika kita melakukan ini, kita memerlukan struktur data yang mendefenisikan daftar item yang ingin kita beli serta daftar item dari masign-masing pemasuk. Ada beberapa komentar yang bisa kita buat terkait algoritma ini. pertama, karena perhitungan biaya didasarkan pada proyeksi. Kita tidak tahu beberapa biaya rata-rata sebenarnya; jika kita meremehkan harga suatu barang, kita akan berakhir di pasar dengan sisa daftar kita. Oleh karena itu, diperlukan cara yang efektif untuk mengembalikan pemasok dengan biaya terendah. 

Selain itu, kita perlu memahami apa yang terjadi ketika membandingkan item di daftar belanja kita dengan barang yang dijual oleh masing-masing penjual, karena jumlah barang yang ada di daftar belanja kita atau jumlah barang yang dijual oleh masing-masing penjual bertambah. Urutan pencarian item dan bentuk struktur data dapat secara signifikan mempengaruhi wakru yang di perlukan untuk melakukan pencarian. Tentunya kita ingin mengatur daftarnya, serta pesanan yang kami kunjungi di setiap penjuak sedemikian rupa untuk menimalkan waktu pencarian. 

perhatikan juga apa yang akan terjadi jika kita mengubah syarat pembelian menjadi harga termurah bukan hanya di bawah harga rata-rata. Alih-alih berpindah secara bertahap dari satu penjual ke penjual lainnya, kita harus menjelajahi pasar suatu hari nanti dan dengan pengetahuan ini, kita dapat memesan daftar belanja kita sesuai dengan penjual yang ingin kita kunjungi. 


Jelas, lebih banyak seluk-belut yang terlibat dalam menerjemahkan masalah dunia nyata ke dalam konstruksi abstrak seperti bahasa pemrograman. Misalnya, saat kita bergerak melalui pasar, pengetahuan kita mengenai biaya satu produk meningkat sehingga perkiraan variabel harga rata-rata menjadi lebih akurat sampai pengetahuan kita mengenai pasar pada perhentian terakhir sempurna. Dengan asumsi semua jenis algoritma pelacakan mundur menimbulkan biaya, kita dapat melihat alasan kita meninjau seluruh strategi kita. Kondisi seperti variabilitas harga tinggi, ukuran dan bentuk struktur data kita, dan biaya penelusuran kembali semuanya menentukan solusi yang paling tepat.


Python untuk data 

Python memiliki beberapa struktur data yang telah ditentukan termasuk daftar, kamus, dan set, yang kita gunakan untuk membuat objek khusus. Selain itu, ada sejumlah pustaka terintegrasi seperti koleksi dan objek matematika yang memungkinkan kita membuat struktur yang lebih kompleks dan melakukan perhitungan padanya. Terakhir, ada pustaka eksternal seperti yang ada di paker SciPy. Hal ini memungkinkan kita untuk melakukan berbagai tugas data lanjutan seperti logistik dan regresi linear, visualisasi, dan perhitungan matematika seperti operasi matriks dan vektor. Perpustakaan eksternal bisa sangat berguna untuk solusi langsung.


Lingkungan python 

Fitur python adalah konsol interaktifnya memungkinkan kita menggunakan python sebagau kalkulator yang dapat diprogram untuk komputer deskop serta lingkungan untuk menulis dan menguji cuplikan kode. read-evaluasi-print Loop dari kosol adalah cara yang sangat nyaman untuk berinteraksi dengan database kode yang lebih besar misalnya untuk fungsi dan metode runtime atau untuk membuat contoh kelas. Ini adalah salah satu keunggulan utama pythin dibandingkan bahasa dikomplasi seperti C / C++ atau Java, dimana write-compile-test-recompile dapat memperpanjang waktu pengembangan secara signifikan dibandingkan dengan loop read-evalu-print python.


Selain CPython versi resmi, ada beberapa distribusi python yang sangat baik. Dua yang populer diantarannya adalah Anaconda dan Canopy. Yang paling penting adalah platform / jupyter yang mencakup lingkungan komputasi web.


Variabel dan Ekspresi 

Untuk menerjemahkan masalah dunia nyata menjadi yang dapat diselesaikan menggunkan algoritma, ada dua tugas yang saling terkait. Pertama pilih variabel dan kemudian temukan ekspresi yang terkait dengan variabel itu.Variabel merupakan label yang dilampirkan ke objek; mereka buka objek itu sendiri. Mereka juga bukan wadah untuk barang. Variabel tidak berisi objek tetapi bertindak sebagai penunjuk atau referensi ke objek. seperti contoh berikut, perhatikanlah :

Bagian ini kami telah membuat variabel a yang menunjuk ke objek daftar. Kami membuat variabel kain b yang menunjuk pada objek daftar yang sama ini. Saat kita menambahkan elemen pada objek daftar ini, perubahan akan terlihat di a dan b. 

python adalah bahasa yang diketik secara dinamis. Setiap nilai adalah tipe, string, atau integer misalnya; ini berarti bahwa ketika kita menganalisasi variabel dengan python, kita tidak perlu mendeklarasikan sebuah tipe. Selain itu, variabel, atau lebih tepatnya objek yang mereka tunjuk, daoat mengubah jenis tergantung pada nilai yang diterapkan padanya, misalnya


 

Lingkup variabel

Sangat penting dalam memahami aturan pelingkupan variabel di dalamnya fungsi. Namespace lokal baru dibuat setiap kali dungsi dijalankan. Mewakili lingkungan lokal yang berisi nama parameter dan variable yang ditentukan oleh fungsi. Agar menyelesaikan namespace saat fungsi dipanggil, interpreter Python akan mencari namespace lokal (yaitu, fungsinya sendiri) dan jika tidak ditemukan ada yang cocok, maka ia akan mencari namespace global. Namespace global ini adalah modul tempat fungsi didefinisikan. Jika namanya masih tidak ditemukan, ia mencari namespace built-in. Akhirnya, jika gagal maka interpreter menampilkan NameError pengecualian. Perhatikan kode berikut:

a = 10; b = 20
def fungsi saya ():
global a
a = 11; b = 21
my_function ()
print (a) #prints 11
print (b) #prints 20


berikut keluaran dari kode sebelumnya:

Dalam kode sebelumnya, kami mendefenisikan dua variabel global. Kita perlu memberi tahu juru bahasa bahwa yang kita maksud adalah variabel global di dalam fungsi, menggunakan kata kunci global. Saat kita mengubah variabel ini menjadi 11, perubahan terlihat dalam cakupan global. Namun, variabel b yang kita setel ke 21 bersifat lokal untuk fungsi tersebut dan perubahan apa pun yang dibuat pada fungsi tersebut tidak terlihat dalam cakupan global.


Kontrol aliran dan iterasi

Program python terdiri dari urutan pernyataan. Ini benar jika kedua file dijalankan sebagai program utama serta file yang dimuat melalui import. Semua pernyataan, termasuk tugas variabel, definisi fungsi, definisi kelas, dan impor modul, memiliki status yang sama. Ada dua cara untuk mengontrol aliran eksekusi program, pernyataan bersyarat dan loop.

Pernyataan if, else, dan elif mengontrol eksekusi pernyataan bersyarat. Format umum adalah rangkaian pernyataan if dan elif yang diikuti dengan pernyataan akhir lain :

x = 'one'
if x == 0 :
print('False')
elif x == 1 :
print('True')
else: print('Something else')
#prints 'something else'


perhatikan penggunaan penggunaan operator == untuk menguji nilai yang sama. Ini mengembalikan true jika nilainya sama; jika tidak makan akan mengembalikan false. Perhatikan juga bahwa menyetel x ke string mengembalikan sesuatu yang berbeda dari hasil kesalahan seperti yang mungkin terjadi dalam bahasa yang diketik secara dinamis. Bahasa yang di ketik secara dinamis seperti python memungkinkan penugasan yang fleksibel dari berbagai jenis objek. Cara lain untuk mengontrol aliran program adalah dengan loop. Mereka dibuat menggunakan while atau for statement, misalnya :


Gambaran umum tipe data dan objek

Python berisi 12 tipe data bawaan. Ini termasuk empat tipe numerik (int, float, complex, bool), empat tipe urutan (str, list, tuple, range), satu tipe pemetaan (dist), dan dua tipe set. Dimungkinkan juga untuk membuat objek yang ditentukan pengguna seperti fungsi atau kelas. 

Semua tipe data di python adalah objek. Faltanya, hampir semuanya adalah ibjek dalam python, termasuk modul, kelas, dan fungsi, serta liberal seperti string dan bilangan bulat. Setiap objekdi python memiliki tipe, nilai, dan identitas. Saat kita menulis greet = "hello world" kita membuat instance objek objek string dengan nilai "hello world" dan identitas greet. Identitas suatu objek bertindak sebagai penunjuk ke lokasi objek dalam memori. Tipe objek, juga dikenal sebagai kelas objek, mendeskripsikan representasi internal objek serta metode dan operasi yang didukungnya. 

selain itu, ada beberapa cara untuk membandingkan objek, misalnya :

jika a == b: #a dan b memiliki nilai yang sama
jika a adalah b: #jika a dan b adalah objek yang sama 
jika tipe (a) adalah tipe(b) : #a dan b adalah tipe yang sama 

Perbedaan penting perlu dibuat antara objek yang bisa diubah dan tidak bisa diubah objeknya. Mereka memiliki metode, seperti insert () atau append (), yang mengubah nilai objek. Objek yang tidak dapat diubah, seperti string, tidak dapat diubah nilainya, jadi saat kita menjalankan metodenya, mereka hanya mengembalikan nilai daripada mengubah nilai objek yang mendasarinya.


String

String adalah objek urutan tetap, dengan ssetiap karakter mewakili elemen dalam urutan. Seperti semua objek, kami menggunakan metode untuk melakukan operasi. String, karena tidak dapat diubah, tidak mengubah instrance; setiap metode hanya mengembalikan nilai. Nilai ini dapat disimpan sebagai variabel lain atau diberikan sebagai argumen untuk argumen untuk fungsi atau metode.

Tabel berikut adalah daftar dari beberapa metode string yang paling umum digunakan dan deskripsinya :


Metode 

Deskripsi

s.count (substring, [start, end]) 

Menghitung kemunculan substring dengan parameter awal dan akhir opsional.

s.expandtabs ([tabsize]) 

Mengganti tab dengan spasi.

s.find (substring, [start, end]) 

Mengembalikan indeks kemunculan pertama substring atau mengembalikan -1 jika substring tidak ditemukan.

s.isalnum () 

Mengembalikan True jika semua karakter 

alfanumerik, mengembalikan False sebaliknya.

s.isalpha () 

Mengembalikan True jika semua karakter adalah alfabet, mengembalikan False jika tidak.

s.isdigit () 

Mengembalikan True jika semua karakter adalah digit, mengembalikan False sebaliknya.

s.join (t) 

Menggabungkan string dalam urutan t.

s.lower () 

Mengubah string menjadi huruf kecil semua.

s.replace (lama, baru [maxreplace]) 

Mengganti substring lama dengan substring baru.

s.strip ([karakter]) 

Menghapus spasi atau karakter opsional.

s.split ([separator], [maxsplit]) 

Memisahkan string yang dipisahkan oleh spasi atau pemisah opsional. Menampilkan daftar.



String, seperti semua jenis urutan, mendukung pengindeksan dan pemotongan. Kita bisa mengambil sepotong string dengan menggunakan s [i: j], di mana i dan j adalah titik awal dan akhir dari potongan tersebut. Kita bisa mengembalikan potongan yang diperpanjang dengan menggunakan langkah seperti berikut ini: s [i: j: stride]. Kode berikut harus menjelaskan hal ini:

Dua contoh pertama cukup mudah, mengembalikan karakter yang terletak di indeks 1 dan tujuh karakter pertama dari string masing-masing. Perhatikan bahwa pengindeksan dimulai dari 0. Dari contoh ketiga, kami menggunakan langkah 2. Ini menghasilkan setiap karakter kedua dikembalikan. Dalam contoh terakhir, kami menghilangkan indeks akhir dan potongan mengembalikan setiap karakter detik di seluruh string.

Kita bisa menggunakan ekspresi, variabel, atau operator apa pun sebagai indeks selama nilainya adalah bilangan bulat, misalnya: 

Operasi umum lainnya yaitu melintasi string dengan loop, misalnya:



Daripada mengubah string, kita perlu mencari cara untuk membangun objek string baru untuk hasil yang kita butuhkan. Sebagai contoh, jika kita ingin memasukkan sebuah kata ke dalam salam kita, kita dapat menetapkan sebuah variabel sebagai berikut:

Seperti yang ditampilkan kode ini, kita menggunakan operator slice untuk membagi string pada posisi indeks 5 dan menggunakan + untuk menggabungkan. Python tidak pernah mengartikan konten string sebagai angka. Jika kita ingin melakukan operasi matematika pada sebuah string, pertama-tama kita perlu mengonversinya menjadi tipe numerik, misalnya:

Lists

Daftar adalah struktur data bawaan yang paling banyak digunakan di Python karena dapat terdiri dari sejumlah data lain jenis. Seperti string, mereka diindeks oleh bilangan bulat yang dimulai dari nol. Tabel berikut berisi metode yang paling umum digunakan daftar dan deskripsi mereka:


Metode 

Keterangan

daftar (s) 

Mengembalikan daftar urutan s.

s.append (x) 

Menambahkan elemen x ke akhir s.

s.extend (x) 

Menambahkan daftar x ke s.

s.count (x) 

Menghitung terjadinya x dalam s.

s.index (x, [start], [stop]) 

Mengembalikan indeks terkecil, i, di mana s [i] == x. Dapat menyertakan indeks start dan stop opsional untuk pencarian.

Python s.insert (i, e) 

Menyisipkan x pada indeks i.

s.pop (i) 

Mengembalikan elemen i dan menghapusnya dari daftar.

s.remove (x) 

Menghapus x dari s.

s.reverse () 

Membalik urutan s.

s.sort (key, [reverse]) 

Mengurutkan s dengan kunci opsional dan sebaliknya.


Saat kita bekerja dengan list, dan kontainer atau objek lainnya, penting untuk memahami mekanisme internal yang digunakan Python untuk menyalinnya. Saat kita menetapkan nilai variabel ke variabel lain, kedua variabel itu menunjuk ke lokasi memori yang sama. Slot baru di memori hanya dapat dialokasikan jika salah satu dari variabel berubah. Ini memiliki konsekuensi penting untuk objek gabungan yang bisa berubah seperti list. Perhatikan kode berikut:

Disini, list1 dan list2 variabel menunjuk ke slot yang sama di memori. Saat kita mengubah y variabel menjadi 4, kita mengubah sama dengan y yang variabel yang list1 ditunjuk. Fitur penting dari list adalah dimana list dapat berisi struktur bersarang, yaitu daftar lain, misalnya:


Contoh berikut ini menunjukkan bagaimana kita bisa menggunakan ini agar memperbarui elemen; di sini kami menaikkan harga tepung sebesar 20 persen:

Cara yang umum dan sangat intuitif untuk membuat list dari ekspresi adalah menggunakan pemahaman list. Ini memungkinkan kita membuat list dengan menulis ekspresi langsung ke dalam list, misalnya:
Ini pada dasarnya menunjukkan dua cara berbeda untuk melakukan komposisi fungsi, di mana kita menerapkan satu fungsi (fungsix * 4) kelainnya (x * 2). Kode berikut mencetak dua list yang mewakili komposisi fungsi f1 dan f2 yang dihitung pertama kali menggunakan for perulangan dan kemudian menggunakan pemahaman list :
def f1 (x): return x*2
def f2 (x): return x*4
lst = []
for i in range (16) :
lst.append (f1 (f2 (i)))

print (lst)
print ([f1 (x) for x in range (64) if x in [f2 (j) for j in range (16)]])

Baris pertama keluaran adalah dari konstruksi loop for. Yang kedua adalah dari ekspresi pemahaman list:

[0, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 88, 104, 112, 120]
[0, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 88, 104, 112, 120]

Pemahaman list juga dapat digunakan untuk mereplikasi aksi loop bersarang dalam bentuk yang lebih kompak. Misalnya, kita mengalikan setiap elemen yang terdapat dalam list1 satu sama lain:

in [13] : list1 = [[1, 2, 3], [4, 5, 6]]
in [14] : [i * j for i in list1 [0] for j in list1 [1]]
out [14] : [4, 5, 6, 8, 10, 12, 12, 15, 18]

Kita juga dapat menggunakan pemahaman list dengan objek lain seperti string, untuk membangun struktur yang lebih kompleks. Misalnya, kode berikut membuat list kata dan jumlah hurufnya:

in [20] : words = 'here is a sentence'.split()
in [21] : [[word, len(word)] for word in wprds]
out [21] : [['here', 4], ['is', 2], ['a', 1], ['sentence', 8]]

Seperti yang akan kita lihat, list membentuk dasar dari banyak struktur data yang akan kita lihat. Fleksibilitas, kemudahan pembuatan, dan penggunaannya memungkinkan mereka membangun struktur data yang lebih terspesialisasi dan kompleks.

Fungsi sebagai objek kelas pertama 

 Kedua fungsi dan kelas adalah apa yang dikenal sebagai objek kelas satu, memungkinkan mereka untuk dimanipulasi dengan cara yang sama seperti tipe data bawaan. Menurut definisi, objek kelas pertama adalah:

  • Dibuat saat runtime
  • Ditugaskan sebagai variabel atau dalam struktur data
  • Diteruskan sebagai argumen ke suatu fungsi
  • Dikembalikan sebagai hasil dari suatu fungsi
Dalam Python, istilah objek kelas pertama merupakan sedikit keliru karena itu menyiratkan semacam hierarki, sedangkan semua objek Python pada dasarnya adalah kelas satu.
Untuk melihat cara kerjanya, mari kita definisikan fungsi sederhana:

def salam (bahasa): 

 if language == 'eng': 

 return 'hello world' 

 if language == 'fr' 

 return 'Bonjour le monde' 

 else: return 'bahasa tidak didukung'


Karena fungsi yang ditentukan pengguna adalah objek, kita bisa melakukan hal-hal seperti memasukkannya ke dalam objek lain, seperti list :
in [9] : l = [greting ('eng'), greeting ('fr'), greeting ('ger')]
in [10] : l[1]
out [10] : ' Bonjour le monde'

Fungsi juga bisa digunakan sebagai argumen untuk fungsi lain. Misalnya, kita dapat mendefinisikan fungsi berikut:

in [14] : def callf(f) :
. . . : lang='eng'
. . . : return (f (lang))
. . . :
in [15] : callf (greeting)
out[15] : 'hello world'


Di sini, callf () mengambil fungsi sebagai argumen, menetapkan variabel bahasa ke 'eng', dan kemudian memanggil fungsi dengan variabel bahasa sebagai argumennya. Kita bisa melihat bagaimana if akan berguna, misalnya for, kita ingin membuat program yang mengembalikan kalimat tertentu dalam berbagai bahasa, mungkin untuk aplikasi bahasa alami. Di sini kita memiliki tempat sentral untuk mengatur bahasa. Selain sapaan fungsi, kita bisa membuat fungsi serupa yang mengembalikan kalimat berbeda. Dengan memiliki satu titik di mana kita mengatur bahasa, logika program lainnya tidak perlu mengkhawatirkan hal ini. Jika kita ingin mengubah bahasa, kita cukup mengubah variabel bahasa dan kita dapat menyimpan yang lainnya tetap sama.

Fungsi orde tinggi 

Fungsi yang mengambil fungsi lain sebagai argumen, atau yang mengembalikan fungsi, disebut fungsi orde tinggi. Python 3 berisi dua fungsi tatanan lebih tinggi bawaan, filter () dan map ().  Fungsi map () menyediakan cara mudah untuk mengubah setiap item menjadi objek yang dapat diulang. Misalnya, berikut ini cara yang efisien dan ringkas untuk melakukan operasi pada suatu urutan. Perhatikan penggunaan lambda fungsi anonim:
in [40] : lst = [1, 2, 3, 4]
in [41] : list(map(lambda x : x**3, lst))
out[41] : [1, 8, 27, 64]

Begitu juga kalo kita dapat menggunakan filter built-in fungsi untuk item filter dalam list:

in [43] : list(filter(lambda x : x<3), lst)
out[43] : [1, 2]

Kelihatannya tidak ada banyak perbedaan dalam karakteristik kinerja selain dari sedikit keunggulan kinerja saat menggunakan fungsi peta dan filter bawaan tanpa lambda operator, dibandingkan dengan pemahaman daftar. Meskipun demikian, sebagian besar panduan gaya merekomendasikan penggunaan pemahaman daftar daripada fungsi bawaan, mungkin karena mereka cenderung lebih mudah dibaca.

Contoh praktis tentang bagaimana fungsi orde tinggi dapat berguna ditunjukkan oleh berikut ini :

in [19] : words = str.split('the longest word in this sentence')
in [20] : sorted(words, key=len)
out[20] : ['in', 'the', 'word', 'this', 'longest', 'sentence']

Berikut adalah contoh lain untuk pengurutan tidak peka huruf besar / kecil: 

in [84] : sl=['A', 'b', 'a', 'c', 'c' ]
in [85] : sl.sort(key=str.lower)
in [86] : sl
out[86] : ['A', 'a', 'b', 'c', 'c' ]
in [87] : sl.sort()
in [88] : sl
in [88] : ['A', 'c', 'a', 'b', 'c' ]


Perhatikan perbedaan antara metode list.sort () dan diurutkan built-in yang fungsi. list.sort (), metode list objek, mengurutkan instance list yang ada tanpa menyalinnya. Metode ini mengubah objek target dan mengembalikan None. Ini sebenarnya menerima objek iterable apa pun sebagai argumen, tetapi akan selalu mengembalikan daftar. Kedua daftar mengurutkan dan diurutkan mengambil dua argumen kata kunci opsional sebagai kunci.

Cara sederhana untuk mengurutkan struktur yang lebih kompleks adalah dengan menggunakan indeks elemen untuk mengurutkan menggunakan lambda operator, misalnya:
in [92] : items.stort(key=lambda item: item[1])
in [93] : items
out[93] : [['flour', 1.9, 5] , ['rice', 2.4, 8], ['corn', 4.7, 6]]

Di sini kita telah mengurutkan item berdasarkan harga.

Fungsi rekursif 

Rekursi adalah salah satu konsep paling mendasar dari ilmu komputer. Untuk menghentikan fungsi rekursif berubah menjadi pengulangan tak terbatas, kita memerlukan setidaknya satu argumen yang menguji kasus penghentian untuk mengakhiri rekursi. Meskipun keduanya melibatkan pengulangan, perulangan iterasi melalui urutan operasi, sedangkan rekursi berulang kali memanggil fungsi. Keduanya membutuhkan pernyataan pemilihan untuk diakhiri.

Secara teknis, rekursi adalah kasus khusus dari iterasi yang dikenal sebagai iterasi ekor, dan biasanya selalu memungkinkan untuk mengubah fungsi berulang menjadi fungsi rekursif dan sebaliknya. Hal yang menarik tentang fungsi rekursif adalah bahwa mereka mampu mendeskripsikan objek tak hingga dalam pernyataan hingga. Kode berikut harus menunjukkan perbedaan antara rekursi dan iterasi. Kedua fungsi ini hanya mencetak angka antara rendah dan tinggi, yang pertama menggunakan iterasi dan yang kedua menggunakan rekursi:


def itertest (low,high) :
while low <= high :
print(low)
low=low+1

def recurtest (low, high):
if low <= high 
print (low)
recurtest(low+1, high)



Contoh rekursif menguji kondisi, mencetak, lalu memanggil dirinya sendiri, menaikkan rendah variabeldalam argumennya. Secara umum, iterasi lebih efisien; Namun, fungsi rekursif seringkali lebih mudah untuk dipahami dan ditulis.

Generator dan rutinitas bersama 

Python berisi fungsi generator, yang merupakan cara mudah untuk membuat iterator dan sangat berguna sebagai pengganti daftar panjang yang tidak bisa berfungsi. Generator menghasilkan item, bukan daftar build. Misalnya, kode berikut menunjukkan mengapa kita mungkin memilih untuk menggunakan generator daripada membuat daftar:


 # membandingkan waktu berjalan daftar dibandingkan dengan waktu impor generator 

 # fungsi generator membuat iterator bilangan ganjil antara n dan m def oddGen (n, m): 

 sementara n <m: 

 yield n 

 n + = 2 

 #membuat daftar jumlah ganjil antara n dan m 

 def oddLst (n, m): 

 lst = [] 

 sedangkan n <m: 

 lst.append (n) 

 n + = 2 

 return lst 

 # waktu yang diperlukan untuk melakukan penjumlahan pada iterator 

 t1 = waktu .time () 

 sum (oddGen (1.1000000)) 

 print ("Waktu untuk menjumlahkan iterator:% f"% (time.time () - t1)) 

 # waktu yang diperlukan untuk membuat dan menjumlahkan daftar 

 t1 = waktu .time () 

 sum (oddLst (1.1000000)) 

 print ("Waktu untuk membangun dan menjumlahkan daftar:% f"% (time.time () - t1))

berikut ini keluarannya :

time to sum an iterator :0.133119
time to buikd and sum a list :0.191172


Peningkatan kinerja sebagai hasil dari penggunaan generator adalah karena nilai dibuat sesuai permintaan, bukan disimpan sebagai daftar di memori. Perhitungan dapat dimulai sebelum semua elemen dibuat dan elemen dibuat hanya jika diperlukan. 


Dalam contoh sebelumnya, penjumlahan metode memuat setiap angka ke dalam memori saat diperlukan untuk penghitungan. Ini dicapai dengan objek generator yang berulang kali memanggil __next __ () metode khusus. Generator tidak pernah mengembalikan nilai selain Tidak Ada

Biasanya, objek generator digunakan untuk loop. Misalnya, kita dapat menggunakan oddcount yang fungsi generatordibuat pada kode sebelumnya untuk mencetak bilangan bulat ganjil antara 1 dan 10:


 untuk i dalam jumlah ganjil (1,10): print (i)


Kita juga dapat membuat ekspresi generator, yang selain mengganti tanda kurung siku dengan tanda kurung, menggunakan sintaks yang sama dan menjalankan operasi yang sama seperti pemahaman daftar. Ini berarti objek generator tidak mendukung metode sekuens seperti append () dan insert (). Namun, Anda dapat mengubah generator menjadi daftar menggunakan fungsi list () :

in [5] : lst1= [1, 2, 3, 4]
in [6] : gen1 = (10**i for i in lst1)
in [7] : gen1
out [7] : <generator objek <genexp> at 0x0000018981504c50>
in [8] : for x in gen1 : print(x)
10
100
1000
10000

Kelas dan pemrograman objek

Kelas adalah cara untuk membuat jenis objek baru dan merupakan pusat pemrograman berorientasi objek. Kelas mendefinisikan sekumpulan atribut yang digunakan bersama di seluruh instance kelas itu. Biasanya, kelas adalah kumpulan fungsi, variabel, dan properti. Tindakan dan logika tentu saja masih ada, tetapi dengan mewujudkannya dalam objek, kami memiliki cara untuk merangkum fungsionalitas, memungkinkan objek untuk berubah dengan cara yang sangat spesifik. Ini membuat kode kita tidak terlalu rentan terhadap kesalahan, lebih mudah untuk diperluas dan dipelihara, dan dapat membuat model objek dunia nyata.

 Kelas biasanya terdiri dari sejumlah metode, variabel kelas, dan properti yang dihitung. Penting untuk dipahami bahwa mendefinisikan kelas tidak dengan sendirinya membuat instance kelas itu. Fungsi yang didefinisikan di dalam kelas disebut metode instance. Mereka menerapkan beberapa operasi ke instance kelas dengan meneruskan instance kelas itu sebagai argumen pertama. Argumen ini disebut diri berdasarkan konvensi, tetapi dapat berupa pengenal hukum apa pun. Berikut adalah contoh sederhana:

 class Employee (object): 

 numEmployee = 0 

 def __init __ (self, name, rate): 

 self.owed = 0 

 self.name = name 

 self.rate = rate 

 Employee.numEmployee + = 1 

 def __del __ (self): 

 Employee.numEmployee - = 1 

 def jam (self, numHours): 

 self.owed + = numHours * self.rate 

 return ("%. 2f hours working"% numHours) 

 def pay (self): 

 self.owed = 0payed 

 return ("% s" % self.name) 

Variabel kelas, seperti numEmployee, berbagi nilai di antara semua instance kelas. Dalam contoh ini, numEmployee digunakan untuk menghitung jumlah instance karyawan. Perhatikan bahwa Karyawan kelasmengimplementasikan __init__ dan __del__ metode khusus, yang akan kita bahas di bagian selanjutnya. 


Kita bisa membuat instance Employee objek, menjalankan metode, dan mengembalikan kelas dan variabel instance dengan melakukan hal berikut:


in [3] : emp1 = employee ('jill', 18.50)
in [4] : emp2 = employee ('jack', 18.50)
in [5] : employee.numEmployee
out[5]: 2
in [6] : emp1.hours(20)
out [6] : '20.00 hours worked'
in [7] : emp1.owed
out[7] : 370.0
in [8] : emp1.pay()
out[8] : 'payed jill'

Metode khusus

Kita dapat menggunakan fungsi dir (objek) untuk mendapatkan daftar atribut dari objek tertentu.  Terlepas dari pengecualian berikut, metode khusus, umumnya dipanggil oleh juru bahasa Python daripada pemrogram; sebagai contoh, saat kita menggunakan + operator, kita sebenarnya memanggil __add __ (). Misalnya, daripada menggunakan my_object .__ len __ () kita bisa menggunakan len (my_object) menggunakan len () pada objek string sebenarnya jauh lebih cepat karena mengembalikan nilai yang mewakili ukuran objek di memori, daripada membuat panggilan ke objek itu. __len__ .

Satu-satunya metode khusus yang kita panggil dalam program kita, sebagai praktik umum, adalah __init__ metode, untuk memanggil penginisialisasi super class dalam definisi kelas kita sendiri. Sangat disarankan agar tidak menggunakan sintaks garis bawah ganda untuk objek Anda sendiri karena potensi konflik saat ini atau masa depan dengan metode khusus Python sendiri.

 Dalam kode berikut, kami membuat kelas yang mengimplementasikan __repr__ metode. Metode ini membuat representasi string dari objek kita yang berguna untuk tujuan pemeriksaan:

class my_class (): 

 def __init __ (self, greet): 

 self.greet = greet 

 def __repr __ (self): 

 return 'a custom object (% r)'% (self.greet)


Saat kita membuat turunan dari objek ini dan memeriksa itu, kita bisa melihat kita mendapatkan representasi string yang disesuaikan. Perhatikan penggunaan % r placeholder format untuk mengembalikan representasi standar objek. Ini berguna dan praktik terbaik, karena, dalam kasus ini, ini menunjukkan kepada kita bahwa greet objek adalah string yang ditunjukkan oleh tanda kutip:

in [13] : a=my_class('giday')
in [14] : a
out [14] : a custom object ('giday')

Warisan

Dimungkinkan untuk membuat kelas baru yang memodifikasi perilaku kelas yang ada melalui pewarisan. Ini sering digunakan untuk mengubah perilaku metode yang ada, misalnya :

 class specialEmployee (Employee): 

 def jam (self, numHours): 

 self.owed + = numHours * self.rate * 2 

 return ("%. 2f hours works"% numHours)


Instance dari special Employee kelas identik dengan Karyawan instance kecuali untuk metode diubah jam () yang.

Untuk sub class untuk mendefinisikan variabel kelas baru, itu perlu mengartikan metode __init __ () , sebagai berikut:

 class specialEmployee (Employee): 

 def __init __ (self, name, rate, bonus): 

 Employee .__ init __ (self, name, rate) #calls the base class self.bonus = bonus 

 def hours (self, numHours): 

 self.owed + = numHours * self.rate + self.bonus 

 return ("%. 2f hours works"% numHours)


Perhatikan bahwa metode kelas dasar tidak dipanggil secara langsung dan kelas turunan harus memanggilnya. Kita dapat menguji keanggotaan kelas menggunakan fungsi built-in isintance(obj1, obj2). Ini mengembalikan nilai true jika obj1 termasuk dalam kelas obj2 atau kelas apa pun yang diturunkan dari obj2.

Metode kelas dijalankan sendiri pada kelas iyu, bukan contoh, dengan cara yang sama bahwa variabel kelas dikaitkan dengan kelas daripada contoh kelas itu. Mereka didefinisikan menggunakan @classmethod dekorator, dan dibedakan dari metode instance di mana kelas diteruskan sebagai argumen pertama. Ini dinamai cls oleh konvensi.

class Aexp (objek): 

 base = 2 

 @classmethod 

 def exp (cls, x): 

 return (cls.base ** x) 

 class Bexp (Aexp): 

 base = 3 


Kelas Bexp mewarisi dari kelas Aexp dan mengubah kelas dasar variabel ke 3. Kita dapat menjalankan kelas induk exp () metode sebagai berikut:

in [4] : bxsqr.sqr(3)
out [4] : 27
Walaupun contoh ini sedikit dibuat-buat, ada beberapa alasan mengapa metode kelas bisa saja berguna. Misalnya, karena sub class mewarisi semua fitur yang sama dari induknya, ada potensi untuk merusak metode yang diwarisi.

Enkapsulasi dan properti data

Kecuali ditentukan lain, semua atribut dan metode bisa diakses tanpa batasan. yang berarti bahwa semua yang didefinisikan dalam kelas dasar dapat diakses dari kelas turunan. Ini juga bisa menyebabkan masalah saat kita hendak membangun aplikasi berorientasi objek di mana kita mungkin ingin menyembunyikan implementasi internal suatu objek. Hal ini dapat menyebabkan konflik namespace antara objek yang ditentukan dalam kelas turunan dengan kelas dasar.

 Untuk mencegah hal ini, metode yang kita definisikan dengan atribut privat memiliki garis bawah ganda, seperti __privateMethod (). Nama metode ini secara otomatis diubah menjadi _Classname__privateMethod () untuk mencegah konflik nama dengan metode yang ditentukan di kelas dasar. Properti adalah sejenis atribut yang alih-alih mengembalikan nilai yang disimpan, menghitung nilainya saat dipanggil. Misalnya, kita bisa mendefinisikan kembali properti exp () dengan yang berikut ini:

 class Bexp (Aexp): 

 __base = 3 

 def __exp (self): 

 return (x ** cls.base) 













Komentar

Postingan populer dari blog ini

Kode Program tentang SEARCHING

Algoritma Sorting Quick Sort

greedy