DERS 30 - Proje 2: Telefon Rehberi

Bu eğitim videosunda beraber Telefon Rehberi adında bir proje geliştiriyoruz.

Sözlüklerin, listelerin, binary dosyaların, pickle ve bu güne kadar anlatılan bir çok konu bu projede işleniyor.

Projenin Kod İncelemesi

Aslında bu proje temel bir yapıya sahip ve sadece tek bir dosyadan oluşuyor. Videodaki koddan çok az farklı bir kodu paylaşıyorum.

Bu projede iki built-in modülü pickle ve os modüllerini kullanıyoruz. Bunun için import etmemiz gerekiyor.

import pickle
import os

Telefon rehberinin verilerinin kayıt olduğu dosyanın ismini global olarak tanımlamak için aşağıdaki tanımı yapıyoruz.

DATA_FILE_NAME = "data.bin"

Menü tekrar tekrar ekrana yazılacağı için bu print'leri bir fonksiyonda bir araya getiriyoruz. Fonksiyonun geri dönüş değeri None olarak belirtilmiş.

def display_menu() -> None:
    print("1. Kayıtları Listele")
    print("2. Kayıt Ara")
    print("3. Kayıt Ekle")
    print("4. Kayıt Sil")
    print("5. Çıkış")
    print()

Eğer kullanıcının girdiği değer yanlış ise tekrar tekrar baştan kullanıcıya doğru değeri girmesini sağlamak için while döngüsüyle sonsuz döngü oluşturup döngünün içinde input fonksiyonunu kullanarak gerekli veriyi almak için aşağıdaki fonksiyonu yazıyoruz.

Döngünün içinde bir if komutu ile kullanıcının girdisini değerlendirip doğru veriyi almayı sağlıyoruz. Doğru verinin öncelikle isdigit metodu ile rakam olup olmadığını kontrol ediyoruz ardından bu girilen değerin 1 ile 5 arası olup olmadığını kontrol ediyoruz. input her zaman string değeri döndüğü için 1 ile 5 arası bir değer olup olmadığını kontrol için integer bir değere dönüştürmemiz gerekiyor. Bunun için int nesnesini kullanıyoruz.

def menu_loop() -> str:
    while True:
        display_menu()
        option = input("Seçenek (1-5): ")
        print("\n")
        if option.isdigit() and 1 <= int(option) <= 5:
            break
    return option

Şimdi programın ana döngüsünü hazırlamamız gerekiyor. Bu döngüyü sonsuz while döngüsü ile oluşturup if ve elif'lerle girilmiş değeri doğru fonksiyona yönlendiriyoruz. Kullanıcı eğer 5 değerini girmiş ise break ile sonsuz döngünün çalışmasını durduruyoruz.

def main_loop() -> None:
    while True:
        option = menu_loop()
        if option == "1":
            list_records()
        elif option == "2":
            search_record()
        elif option == "3":
            add_record()
        elif option == "4":
            delete_record()
        elif option == "5":
            break

Telefon rehberinin dört ana işlevini aşağıdaki fonksiyonlarla tanımlıyoruz.

def list_records() -> None:
    record_list = read_file()
    print_record_list(record_list)


def search_record() -> None:
    print("Kayıt Arama")
    name = input("İsim: ")
    surname = input("Soyisim: ")
    if name == "" or surname == "":
        print("Hatalı Giriş\n")
    record_list = search_record_from_file(name, surname)
    print_record_list(record_list)


def add_record() -> None:
    print("Yeni Kayıt Ekle")
    name = input("İsim: ")
    surname = input("Soyisim: ")
    tel_number = input("Telefon Numarası: ")
    print(f"Yeni Kayıt: {name} {surname} - {tel_number}")
    if are_you_sure():
        add_record_to_file(name, surname, tel_number)
        print("Kayıt Eklendi\n")


def delete_record() -> None:
    print("Kayıt Silme")
    name = input("İsim: ")
    surname = input("Soyisim: ")
    if name == "" or surname == "":
        print("Hatalı Giriş\n")
    record_list = search_record_from_file(name, surname)
    print_record_list(record_list)
    if are_you_sure():
        delete_records_from_file(record_list)
        print("Kayıtlar Silindi.\n")

Bu dört işlemin işlevleri için dosya üzerinde yapılan işlemleri için aşağıdaki fonksiyonları tanımlıyoruz.

def search_record_from_file(name_param:str, surname_param:str) -> list:
    record_list = read_file()
    response_list = list()
    for record in record_list:
        if record.get("name").upper() == name_param.upper() and record.get("surname").upper() == surname_param.upper():
            response_list.append(record)
    return response_list



def add_record_to_file(name_param : str, surname_param:str, tel_number_param:str) -> None:
    record_list = read_file()
    record_dict = dict(name=name_param, surname=surname_param, tel_number=tel_number_param)
    record_list.append(record_dict)
    write_file(record_list)


def delete_records_from_file(record_list_param : list) -> None:
    record_list = read_file()
    for record_for_delete in record_list_param:
        record_list.remove(record_for_delete)
    write_file(record_list)

Liste içeriğinden gerekli verileri terminale yazdıran fonksiyonu yazıyoruz.

def print_record_list(record_list: list) -> None:
    print(f"Kayıt Sayısı: {len(record_list)}\n")
    print(f"{'İsim-Soyisim':^20} | {'Telefon No':^11}")
    for record in record_list:
        name_surname = f"{record.get('name', '')} {record.get('surname', '')}"
        print(f"{name_surname:20.20} - {record.get('tel_number', ''):11.11}")
    print()

Eminmisiniz sorusunu sormak için aşağıdaki fonksiyonu yazıyoruz. Bu fonksiyon bool değeri dönüyor yani eğer kullanıcı e veya E girmişse True, eğer h veya H girilmişse False değerini dönecektir.

def are_you_sure() -> bool:
    while True:
        answer = input("Eminmisiniz? (E)evt/(H)ayır --> ")
        print()
        if answer.upper() == "E":
            return True
        elif answer.upper() == "H":
            return False

Aşağıdaki fonksiyonlarda pick modülü kullanarak listemizi olduğu gibi içindeki değerlerle birlikte dosyaya yazdırıyoruz. os modülünün isfile fonksiyonunu kullanarak dosya isminin bir dosyayımı yoksa bir klasörümü ifade ediyor kontrol ediliyor.

def read_file() -> list:
    if os.path.isfile(DATA_FILE_NAME):
        with open(DATA_FILE_NAME, "rb") as file_object:
            record_list = pickle.load(file_object)
    else:
        record_list = list()
    return record_list


def write_file(record_list_param: list) -> None:
    with open(DATA_FILE_NAME, "wb") as file_object:
        pickle.dump(record_list_param, file_object)

Ana döngümüzü çalıştırmak için main_loop fonksiyonumuzu çağırıyoruz. Bu çalıştırma sadece name global sihirli değişkenin değeri __main__ ise çalışması sağlanır.

if __name__ == "__main__":
    main_loop()

DERSLER