Python - Sınıf İçerisindeki Fonksiyonları Kullanamıyorum?

Merhaba,

Alttaki kod yapısı sorunsuz çalışmaktadır.


import sqlite3

con = sqlite3.connect("database.db")
cursor = con.cursor()
cursor.execute("CREATE TABLE IF NOT EXISTS CREDIT_CARD (DATE TEXT, DETAIL TEXT, SUM FLOAT)")
con.commit()

class CreditCardRegister():

    def __init__(self, date, detail, spend):
        self.date = date
        self.detail = detail
        self.spend = spend
        cursor.execute("INSERT INTO CREDIT_CARD VALUES(?,?,?)", (date, detail, spend))
        con.commit()


while True:
    print("ADD SUM == 1")
    print("SHOW SUM == 2")
    print("SHOW DEBIT == 3")
    print("FOR EXIT == exit")
    print()
    select = input("YOUR SELECT == ")

    if select == "1":
        add_date = input("DATE == ")
        add_detail = input("DETAIL == ")
        add_spend = input("SPEND == ")
        print()
        ccx = CreditCardRegister(add_date, add_detail, add_spend)

    else:
        break

fakat aynı kod yapısını şu hale getirdiğimiz zaman çalışmıyor. sebebini az çok anladım ama anladığım sebep ve uygulamaya çalıştığım çözümler bana yardımcı olmadı


import sqlite3

con = sqlite3.connect("database.db")
cursor = con.cursor()
cursor.execute("CREATE TABLE IF NOT EXISTS CREDIT_CARD (DATE TEXT, DETAIL TEXT, SUM FLOAT)")
con.commit()


class CreditCardRegister():
    name = "ALBARAKA"

    def __init__(self, date, detail, spend, name):
        self.date = date
        self.detail = detail
        self.spend = spend
        self.name = name
        cursor.execute("INSERT INTO CREDIT_CARD VALUES(?,?,?)", (date, detail, spend))
        con.commit()

    def show(self):
        cursor.execute("SELECT * FROM CREDIT_CARD")
        credit_card_data = cursor.fetchall()
        for i in credit_card_data:
            print("BANK NAME == {} | {}".format(self.name, i))


while True:
    print("ADD SUM == 1")
    print("SHOW SUM == 2")
    print("SHOW DEBIT == 3")
    print("FOR EXIT == exit")
    print()
    select = input("YOUR SELECT == ")

    if select == "1":
        add_date = input("DATE == ")
        add_detail = input("DETAIL == ")
        add_spend = input("SPEND == ")
        print()
        ccx = CreditCardRegister(add_date, add_detail, add_spend)

    elif select == "2":
        ccx.show()

ccx.show() çalışmadığından bahsediyorum. Kendimce okuma yorumumdan sonra hatanın "ccx’in sınıfa atanmadığından dolayı çalıştıracağı değerleri falan belirtmediği içindir diye düşündüm. çünkü döngü yapısından oluştuğu için döngü de sadece else select == "2": ccx atanmadığı sınıfın tanımadığı özelliğini çalıştırmayacak. anladığım bu oldu. Çözüm olarak şöyle bir yol izledim;


elif select == "2":
        ccx = CreditCardRegister(add_date, add_detail, add_spend, name)
        ccx.show()

fakat burada da şu sıkıntı oldu ccx’e sınıfını tanıtırken içerisine değerler göndermem gerektiği için programın en başına değerleri “None” olarak tanımladım. else select == "2": çalıştığı zaman otomatik olarak def __init__() de çalıştığı için veri tabanında her çalıştığı zaman boş kayıtlar oluşturmaya başlıyor. İş iyice karmaşıklaştı ve ben boğuldum.


Yapmak istediğim tam olarak şu bir sınıf belirlemek ve bu sınıfın içerisinde 2 işlem gerçekleşmesi. bu işlemin aynısını 2 farklı dosya oluşturup kod kalabalığı yaparak sağlıyorum. Ama daha sade ve az kod yazarak yapmanın mümkün olduğu aşikar. Belirlenecek sınıfın içerisinde bir “kredi kartı harcaması ekleme fonksiyonu” birde “kredi kartı harcamaları gösterme fonksiyonu” olacaktı. böylelikle değişkenler tek bir bloktan derlenecek haliyle az kod yazılmış olacak.


Not = nesne tabanlı programlamada yeniyim. iyice kavramak için sürekli tekrar ediyorum örnekler oluşturarak pekiştirmeye çalışıyorum.

Şimdiden yardımı olanlara teşekkürler <3

KODUN SON HALİ EKTEDİR


import sqlite3

add_date = None
add_detail = None
add_spend = None
name = "ALBARAKA"

con = sqlite3.connect("database.db")
cursor = con.cursor()
cursor.execute("CREATE TABLE IF NOT EXISTS CREDIT_CARD (DATE TEXT, DETAIL TEXT, SUM FLOAT)")
con.commit()


class CreditCardRegister():

    def __init__(self, date, detail, spend, name):
        self.date = date
        self.detail = detail
        self.spend = spend
        self.name = name
        cursor.execute("INSERT INTO CREDIT_CARD VALUES(?,?,?)", (date, detail, spend))
        con.commit()

    def show(self):
        cursor.execute("SELECT * FROM CREDIT_CARD")
        credit_card_data = cursor.fetchall()
        for i in credit_card_data:
            print("BANK NAME == {} | {}".format(self.name, i))


while True:
    print("ADD SUM == 1")
    print("SHOW SUM == 2")
    print("SHOW DEBIT == 3")
    print("FOR EXIT == exit")
    print()
    select = input("YOUR SELECT == ")

    if select == "1":
        add_date = input("DATE == ")
        add_detail = input("DETAIL == ")
        add_spend = input("SPEND == ")
        print()
        ccx = CreditCardRegister(add_date, add_detail, add_spend, name)

    elif select == "2":
        ccx = CreditCardRegister(add_date, add_detail, add_spend, name)
        ccx.show()

Kodun ikinci halinde ccx'in tanimsiz olmasi sorunu, kodun son halinde add_* degiskenlerinin tanimsiz olmasi sorununa donusmus. Yani aslinda cozulen bir sey yok, sorun ayni; sadece sorunun etrafindan dolanilmaya calisilmis.

Sorunun etrafindan dolanilamamasinin sebebi de Python veya OOP sorunu degil, mantik sorunu olmasi: ADD SUM komutu verilmeden SHOW SUM komutu oldugunda ne olacak?


CreditCardRegister bir obje olarak degil, bir fonksiyon olarak kullanilmis: yaratildigi anda is yapiliyor, hatta database’e kayit ekleme gibi buyuk bir is yapiliyor. Oysa obje constructor’larinin is yapmak icin degil, objeyi bilinen/tanimli/dogru bir state’e getirmek icin kullanilmalari lazim.

OOP’nin temel mantigi:

  • Obje (sinif), state’i temsil eden degiskenler ve state’i degistiren fonksiyonlarin birlesimidir
  • Bir obje her zaman bilinen/tanimli/dogru bir state’te durur
  • Obje sifirdan yaratildiginda bundan emin olmanin sorumlulugu constructor’dadir
  • Objenin state’i metod cagrilari ile degisir
  • Degisen state’ten emin olmanin sorumlulugu degistiren metoddadir

(“state nedir” diye sorarsan "objenin icinde tutulan durum"dan daha iyi bir tanim veremem :frowning: )


ccx her zaman gereken bir obje olduguna gore sadece ADD SUM durumunda degil, her sekilde yaratman lazim.

1 Beğeni

constructor’ları iş yapmak için değil yapılan bir işin özelliklerini tutacağım yer olacak. söylediklerinizden bunu anladım.

böyle bir konu açmıştım oradaki eksiklerimi tamamlamaya çalışıyorum. kod bloklarım da sizin de söylediğiniz gibi mantık hataları var. Bu mantık hatalarını çözmenin yolu düşünmekten geçer diye biliyorum. Ama o mantık hatalarını nasıl yakalayacağım konusunda beynim de boşluklar var.

Tam olarak sorunun ne olduğunu anlamakta güçlük çektim üstteki kodlarda. Bir sorun olduğunu biliyorum farkındayım ama neresine dokunmam gerekiyor onu çözemeyip dediğiniz gibi “etrafında dolaşarak” girdabın içine çekilip boğuldum.

Sanırım en geriye dönüp biraz daha algoritma çalışmam gerekiyor. Cevabınız için teşekkürler ben tekrar farklı tarzlarda yaklaşarak değişiklikler yapayım. Teşekkürler

Şöyle yapsanız olmaz mı?

#!/usr/bin/python3.8
# -*- coding: utf-8 -*-

import sqlite3

con = sqlite3.connect("database.db")
cursor = con.cursor()
cursor.execute(
    "CREATE TABLE IF NOT EXISTS CREDIT_CARD(DATE, DETAIL, SPEND, NAME)"
)
con.commit()


class CreditCardRegister():
    def __init__(self, date, detail, spend, name):
        self.date = date
        self.detail = detail
        self.spend = spend
        self.name = name
        cursor.execute(
            "INSERT INTO CREDIT_CARD VALUES(?,?,?,?)", 
            (date, detail, spend, name)
        )
        con.commit()

    @classmethod
    def show(cls):
        cursor.execute("SELECT * FROM CREDIT_CARD")
        credit_card_data = cursor.fetchall()
        for i in credit_card_data:
            print("BANK NAME == {} | {}".format(i[3], i[:3]))


while True:
    print("ADD SUM == 1")
    print("SHOW SUM == 2")
    print("SHOW DEBIT == 3")
    print("FOR EXIT == exit")
    print()
    select = input("YOUR SELECT == ")
    if select == "1":
        add_date = input("DATE == ")
        add_detail = input("DETAIL == ")
        add_spend = input("SPEND == ")
        add_name = input("NAME == ")
        print()
        CreditCardRegister(add_date, add_detail, add_spend, add_name)

    elif select == "2":
        CreditCardRegister.show()

tam istediğim gibi çalıştı şimdi okuyacağım kodları

Pardon, benim icin de zor bir sey mantik hatalarinin tam noktalarini veya -daha onemlisi- sebeplerini kestirip soyleyebilmek. Deniyorum ama:

Simdi burada CreditCardRegister bir adet harcamayi mi temsil ediyor?

Yaratildiginda DB’de ilgili bir row yaratiliyor. (Ama DB’de row yaratildiginda CreditCardRegister objesi yaratilmiyor—yani burada bir senkronizasyon problemi var. Program kapandiginda mesela CCR objeleri yok oluyor ama DB satirlari kaliyor.)

Eger tek bir harcamayi temsil ediyorsa show fonksiyonu neden birden fazla harcama gosterebiliyor? Hatta butun harcamalari inceliyor?

Harcamalarin hem biri hem de hepsiyle ilgilenen bir class ise klasik OOP anlaminda bir class degil bu, ilgili fonksiyonlarin ayni isim altinda toplandigi bir obje olabilir. Eger oyleyse self. degiskenleri gibi, __init__ gibi state degistiren fonksiyonlar icermemesi lazim; her fonksiyonun girdisi parametre olarak girip return value olarak cikmali.

Eger klasik anlamda bir OOP sinifina donusturulecekse de sorumluluk alanlari, temsil ettigi seyler ve ne zaman dogup ne zaman olecegi belirlenmeli. (Mesela: bu bir harcamadir, harcama yapildigindan bundan bir tane yaratilip DB’ye kaydedilir, dokum alinirken dokumdeki her satir icin bir tane bundan dondurulur, vb.)

ben veri tabanına kayıt olustururken daima ihtiyacım olan verileri kayıt ettim ama o verileri kayıt ederken oluşturan yapı ve değişkenleri de kayıt etmeyi hiç akıl etmedim. çok mantıklı dediğiniz;

Bu çok önemli bir ayrıntı veri tabanında satırlara bakıldığı zaman sadece veri kayıt edildiği anlaşılıyor ama bu verilerin nereden geldiğini nasıl geldiğini kayıt altına alan bir kısım yok. Normalde bu kodları şöyle çalıştırıyordum. class yerine fonksiyon belirleyip import ederek çalıştırıyordum. Örnek kod;


Bu kayıt ekleme ekranı;


import time
import sqlite3
from fonksiyonlar import _0log
from datetime import datetime

def add(username):
    
    bankname = "ALBARAKA"
    screenname = bankname + " KAYIT"
    
    print("---------------------------------------------------------------------------------------------------------------------------------")
    time.sleep(0.1)
    print("| KULLANICI = {} | HOSGELDINIZ | EKRAN = {} | TARIH = {}  |".format(username,screenname,datetime.now()))
    time.sleep(0.1)
    print("---------------------------------------------------------------------------------------------------------------------------------")
    print()
    time.sleep(0.1)

    while True:

        date = input("TARIH = ")
        typ3 = input("TYPE = ")
        info = input("ACIKLAMA = ")
        
        _0log._00add00(username,date,typ3,info)

        if len(date)==0:
            print()
            print("BOS KAYIT YAPILAMAZ!")
            print()
            
            _0log._00add01(username)

        elif len(typ3)==0:
            print()
            print("BOS KAYIT YAPILAMAZ!")
            print()
            
            _0log._00add01(username)

        elif len(info)==0:
            print()
            print("BOS KAYIT YAPILAMAZ!")
            print()
            
            _0log._00add01(username)

        else:
            break

    while True:

        cash = input("TUTAR = ")

        try:

            cash = float(cash)

            break

        except:

            print()
            print("LUTFEN SAYISAL GIRIS YAPINIZ!")
            print()
            
            _0log._00add01(username)

    print()
    print("BILGILERINIZ KAYIT EDILIYOR LUTFEN BEKLEYINIZ")
    print()
    time.sleep(1)

    cash = float(cash)

    con = sqlite3.connect("database/database.db")
    cursor = con.cursor()
    cursor.execute("INSERT INTO albaraka VALUES(?,?,?,?)",(date,typ3,info,cash))
    con.commit()
    
    _0log._00add02(username,date,typ3,info,cash)

    print("BILGILERINIZ KAYIT EDILDI.")
    print()
    cursor.execute("SELECT TUTAR FROM albaraka")
    data = cursor.fetchall()
    bakiye = 0
    for i in data:
        bakiye+=i[0]
    print("Güncel Bakiyeniz = {} TL".format(bakiye))
    time.sleep(1)
    time.sleep(1)
    con.close()

Bu da kayıt gösterme ekranı


import time
import sqlite3
from fonksiyonlar import _0log, _6invalid
from datetime import datetime

def show(username):
    
    while True:
        
        bankname = "ALBARAKA"
        
        _0log._00see00(username,bankname)

        screenname = bankname + " GOSTER"

        print("---------------------------------------------------------------------------------------------------------------------------------")
        time.sleep(0.1)
        print("| KULLANICI = {} | HOSGELDINIZ | EKRAN = {} | TARIH = {}  |".format(username,screenname,datetime.now()))
        time.sleep(0.1)
        print("---------------------------------------------------------------------------------------------------------------------------------")
        print()
        time.sleep(0.1)
        print("HESAP HAREKETLERI ICIN = 1")
        time.sleep(0.1)
        print("BAKIYE GORMEK ICIN = 2")
        time.sleep(0.1)
        print("BIR UST MENU ICIN = exit")
        time.sleep(0.1)
        print()
        print("LUTFEN BIR SECIM YAPINIZ")
        time.sleep(0.1)
        print()
        select = input("Seçiminiz = ")
        
        _0log._00see01(username,select)

        print()
        time.sleep(1)

        if (select == "1"):
            
            con = sqlite3.connect("database/database.db")
            cursor = con.cursor()
            cursor.execute("SELECT * FROM albaraka")
            data = cursor.fetchall()
            con.close()

            for i in data:
                time.sleep(0.1)
                print(i)

        elif (select == "2"):
            
            _0log._00see03(username,bankname)

            con = sqlite3.connect("database/database.db")
            cursor = con.cursor()
            cursor.execute("SELECT TUTAR FROM albaraka")
            data = cursor.fetchall()
            bakiye = 0
            for i in data:
                bakiye+=i[0]
            print("Bakiyeniz = ",bakiye)

        elif (select == "exit"):
            
            _0log._00see04(username,bankname)
            
            break

        else:
            _0log._06invalid00(select)
            
            _6invalid.invalid()

Normal şartlarda bu iki fonksiyon farklı dosyalarda tanımlanıp çağrıldığı zaman benim işimi yeterince görüyor ama dediğim gibi oluşturulan kod bloklarında çok fazla kod var. Daha sade bir şekilde bunu halledebileceğimi düşünüyorum sürekli. Kendi banka hareketlerimi kontrol edip saklayıp takip edebildiğim bir sistemim var. Ama yapıp geçmiş olmak yerine aynı sistemi geliştirmeye çalışıyorum. Bunu ilk yaptığım ile son yaptığım arasında %32 daha az kod yazmışım. bu beni çok mutlu etti çünkü bu kadar az kod yazarak daha fazla iş yaptırabildim uygulamama. Benim nesne tabanlı programlamada kendimi geliştirebilmem için bol bol örnek yapmaya proje oluşturmaya ihtiyacım var. Tavsiye edeceğiniz kaynak ya da örnek göstereceğiniz kod blokları varsa okuyup geliştirmek çok işime yarar.