Skip to content

13. [BaseEntity] ve [MyException] genel sınıfları

Şimdi, bundan sonra düzenli olarak kullanacağımız iki sınıf tanımlıyoruz.

Image

13.1. MyException sınıfı

[MyException] (MyException.py) sınıfı, özel bir istisna sınıfı sağlar:


# [BaseException]'ten türetilen özel bir istisna sınıfı
class MyException(BaseException):
    # yapıcı
    def __init__(self: object, code: int, message: str):
        # üst sınıf
        BaseException.__init__(self, message)
        # hata kodu
        self.code = code

    # toString
    def __str__(self):
        return f"MyException[{self.code}, {super().__str__()}]"

    # getter
    @property
    def code(self) -> int:
        return self.__code

    # setter
    @code.setter
    def code(self, code: int):
        # hata kodu pozitif bir tamsayı olmalıdır
        if isinstance(code, int) and code > 0:
            self.__code = code
        else:
            # istisna
            raise BaseException(f"code erreur {code} incorrect")

Notlar

    1. satır: [MyException] sınıfı, önceden tanımlanmış [BaseException] sınıfından türetilmiştir;
    1. satır: Oluşturucu iki parametre kabul eder:
    2. [code]: tamsayı bir hata kodu;
    3. [message]: bir hata mesajı;
    1. satır: hata mesajı üst sınıfa aktarılır;
  • satır 14-27: [code] özniteliği bir getter / setter aracılığıyla işlenir;
  • 23-24. satırlar: [code] özniteliğinin geçerliliği kontrol edilir: bu özniteliğin >0 bir tamsayı olması gerekir;

13.2. [BaseEntity] sınıfı

[BaseEntity] sınıfı, bir nesne hakkındaki bilgileri kapsüllemek için oluşturacağımız sınıfların çoğunun üst sınıfı olacaktır. Bundan sonra esas olarak iki tür sınıf kullanacağız:

  • tek bir nesneye ait bilgileri tek bir yerde kapsüllemek amacıyla oluşturulan sınıflar. Bu sınıfların, getter/setter yöntemleri ve bir görüntüleme işlevi (__str__) dışında başka davranışları (yöntemleri) olmayacaktır. Yönetilecek N nesne varsa, bu sınıflar N kez örneklenir. [BaseEntity], bu tür sınıfların üst sınıfı olacaktır;
  • ana işlevi yöntemleri ve çok az miktarda bilgiyi kapsüllemek olan sınıflar. Bu sınıflar yalnızca bir kez örneklenecektir (singleton). Görevleri, bir uygulamanın algoritmalarını uygulamaktır;

[BaseEntity] sınıfı şöyledir:


# ithalatlar
import json
import re

from MyException import MyException


class BaseEntity(object):
    # sınıf durumundan hariç tutulan özellikler
    excluded_keys = []

    # sınıf özellikleri
    @staticmethod
    def get_allowed_keys() -> list:
        # id: nesnenin kimliği
        return ["id"]

    # toString
    def __str__(self) -> str:
        return self.asjson()

    # getter
    @property
    def id(self) -> int:
        return self.__id

    #  setter
    @id.setter
    def id(self, id):
        # id, 0'dan büyük bir tamsayı olmalıdır
        try:
            id = int(id)
            erreur = id < 0
        except:
            erreur = True
        # hata mı?
        if erreur:
            raise MyException(1, f"L'identifiant d'une entité {self.__class__} doit être un entier >=0")
        else:
            self.__id = id

    def fromdict(self, state: dict, silent=False):
        

    def set_value(self, key: str, value, new_attributes) -> dict:
        

    def asdict(self, included_keys: list = None, excluded_keys: list = []) -> dict:
        

    def asjson(self, excluded_keys: list = []) -> str:
        

    def fromjson(self, json_state: str):
        

Açıklamalar

  • [BaseEntity] sınıfının amacı, Nesne / Sözlük ve Nesne / jSON dönüşümlerini kolaylaştırmaktır. Bu sayede aşağıdaki yöntemler sunulmaktadır:
    • [asdict]: nesnenin özellik sözlüğünü döndürür;
    • [fromdict]: bir sözlükten bir nesne oluşturur;
    • [asjson]: jSON nesnesinin dizesini, [__str__] işlevinin yaptığı gibi döndürür;
    • [fromjson]: jSON dizesinden bir nesne oluşturur;
  • [BaseEntity] sınıfı, olduğu gibi kullanılmak üzere değil, türetilmek üzere tasarlanmıştır;
  • 22-25. satırlar: [BaseEntity] sınıfının tek bir özelliği vardır: [id] tamsayı. Bu özellik, nesnenin tanımlayıcısıdır. Uygulamada, aynı sınıfa ait örnekleri birbirinden ayırt edebilmek genellikle yararlıdır. Bunu, bir örnekte benzersiz olan bu özellik sayesinde yapacağız. Ayrıca, nesneler genellikle birincil anahtarla (genellikle bir tamsayı) tanımlandıkları veritabanlarından gelir. Bu durumlarda, [id] birincil anahtar olacaktır;
  • 27-40. satırlar: [id] özelliğinin setter'ı. Değerin >=0 olan bir tamsayı olup olmadığı kontrol edilir. Aksi takdirde, [MyException] türünde bir istisna atılır (39. satır);
  • satır 10: [excluded_keys], bir sınıf özniteliğidir, örnek özniteliği değildir. Dolayısıyla [BaseEntity.excluded_keys] yazılacaktır. Bu sınıf özniteliği, Nesne / Sözlük ve Nesne / jSON dönüşümlerine dahil olmayan sınıf özelliklerini içeren bir listedir;
  • 12-16. satırlar: [get_allowed_keys], sınıfın özelliklerinin listesini döndürür. Bir Sözlük -> Nesne veya jSON -> Nesne dönüştürmesinde, yalnızca bu listede bulunan anahtarlar kabul edilecektir. [BaseEntity] sınıfından türetilen her sınıf bu listeyi yeniden tanımlamalıdır;

Burada, [BaseEntity] sınıfının özelliklerine ve işlevlerine, [BaseEntity] sınıfından türetilen sınıfların erişebileceğini anlamak gerekir. Anlaşılması gereken önemli nokta budur.

Şimdi [BaseEntity] sınıfının kodunu ayrıntılı olarak inceleyeceğiz. Bu kod oldukça ileri düzeydedir. Yeni başlayan okuyucular, kodun ayrıntılarına girmeden her fonksiyonun işlevini okumakla yetinebilirler.

13.2.1. [BaseEntity.fromdict] yöntemi

13.2.1.1. Définition

[fromdict] yöntemi, bir sözlükten [BaseEntity] nesnesini veya bunun türevlerini başlatmaya olanak tanır:


def fromdict(self, state: dict, silent=False):
        # nesne güncelleniyor
        # izin verilen anahtarlar
        allowed_keys = self.__class__.get_allowed_keys()
        # durum anahtarlarını tarıyor
        for key, value in state.items():
            # anahtar izinli mi?
            if key not in allowed_keys:
                if not silent:
                    raise MyException(2, f"la clé {key} n'est pas autorisée")
            else:
                # anahtara değer atanmaya çalışılıyor
                # olası istisnanın yukarıya iletilmesine izin veriliyor
                setattr(self, key, value)
        # nesne döndürülüyor
        return self

Açıklamalar

    1. satır: İşlev, mevcut nesnenin başlatılacağı [state] sözlüğünü parametre olarak alır;
    1. satır: [fromdict] işlevini çağıran sınıfın [get_allowed_keys] statik işlevi çağrılır. Eğer [BaseEntity] sınıfından türetilmiş bir sınıfla uğraşıyorsak ve bu türetilmiş sınıf [get_allowed_keys] statik işlevini yeniden tanımlamışsa, o zaman [get_allowed_keys] işlevi çağrılır. Her türetilmiş sınıf, kendi özelliklerini tanımlamak için bu statik fonksiyonu yeniden tanımlar;
    1. satır: [state] sözlüğünün anahtarları ve değerleri taranır;
    1. satır: [key] anahtarı sınıfın özellikleri arasında yer almıyorsa, o zaman:
    2. bu anahtar göz ardı edilir;
    3. bir istisna atılır (satır 10). Geliştirici, doğru [silent] parametresini geçirerek ne istediğini belirtir (satır 1). [silent]'in varsayılan değeri, nesneyi sahip olmadığı bir özellik ile başlatmaya çalışılırsa bir istisna atılmasını sağlar;
    1. satır: anahtar, nesnenin özellikleri arasında yer alıyorsa, önceden tanımlanmış [setattr] işlevi kullanılarak [self] nesnesine atanır;
    1. satır: İşlev, nesneyi başlatılmış olarak döndürür;

13.2.1.2. Exemples

Image

13.2.1.2.1. [Utils] sınıfı

[Utils] (Utils.py) sınıfı şu şekildedir:


class Utils:
    # statik yöntem
    @staticmethod
    def is_string_ok(string: str) -> bool:
        # string bir dize mi
        erreur = not isinstance(string, str)
        if not erreur:
            # dize boş mu?
            erreur = string.strip() == ''
        # sonuç
        return not erreur

Bu sınıf, 3-11. satırlarda, [str] parametresi boş olmayan bir karakter dizisiyse boole değerini true olarak döndüren statik bir yöntem tanımlar;

13.2.1.2.2. [Personne] sınıfı

[Personne] (Personne.py) sınıfı, [BaseEntity] sınıfından türetilmiştir:


# ithalatlar
from BaseEntity import BaseEntity
from MyException import MyException
from Utils import Utils


# Personne sınıfı
class Personne(BaseEntity):
    # sınıf durumundan hariç tutulan özellikler
    excluded_keys = []

    # sınıf özellikleri
    # kimlik: kişinin kimlik numarası
    # ad: kişinin adı
    # soyadı: kişinin soyadı
    # yaş: kişinin yaşı
    @staticmethod
    def get_allowed_keys() -> list:
        # id: nesnenin kimliği
        return BaseEntity.get_allowed_keys() + ["nom", "prénom", "âge"]

    # alıcılar
    @property
    def prénom(self) -> str:
        return self.__prénom

    @property
    def nom(self) -> str:
        return self.__nom

    @property
    def âge(self) -> int:
        return self.__âge

    # ayarlayıcılar
    @prénom.setter
    def prénom(self, prénom: str):
        # ad boş olmamalıdır
        if Utils.is_string_ok(prénom):
            self.__prénom = prénom.strip()
        else:
            raise MyException(11, "Le prénom doit être une chaîne de caractères non vide")

    @nom.setter
    def nom(self, nom: str):
        # ad alanı boş olmamalıdır
        if Utils.is_string_ok(nom):
            self.__nom = nom.strip()
        else:
            raise MyException(12, "Le nom doit être une chaîne de caractères non vide")

    @âge.setter
    def âge(self, âge: int):
        # yaş, 0'dan büyük bir tamsayı olmalıdır
        erreur = False
        if isinstance(âge, int):
            if âge >= 0:
                self.__âge = âge
            else:
                erreur = True
        else:
            erreur = True
        # hata mı?
        if erreur:
            raise MyException(13, "L'âge doit être un entier >=0")
    1. satır: [Personne] sınıfı, [BaseEntity] sınıfından türetilmiştir;
  • 8-65. satırlar: Daha önce karşılaştığımız [Personne] sınıfının temel özellikleri korunmuştur. Farklılıklar şunlardır:
    • sınıfta artık oluşturucu yoktur;
    • sınıf, [MyException] istisnasını kullanır (örnek: 65. satır);
    • sınıfın, özelliklerinin listesini tanımlayan [get_allowed_keys] adlı statik bir yöntemi vardır (satır 17-20). [Personne] sınıfına özgü özellikler, üst sınıf olan [BaseEntity] sınıfının özelliklerine eklenmiştir;
    • bu sınıfın, daha sonra tekrar ele alacağımız [excluded_keys] adlı bir statik listesi vardır;
13.2.1.2.3. [Enseignant] sınıfı

[Enseignant] (Enseignant.py) sınıfı, [Personne] sınıfından türetilmiştir:


# ithalatlar
from MyException import MyException
from Personne import Personne
from Utils import Utils


# Öğretmen sınıfı
class Enseignant(Personne):
    # sınıf durumundan hariç tutulan özellikler
    excluded_keys = []

    # sınıf özellikleri
    # id: kişinin kimlik numarası
    # ad: kişinin adı
    # soyadı: kişinin soyadı
    # yaş: kişinin yaşı
    # ders: öğretilen ders
    @staticmethod
    def get_allowed_keys() -> list:
        # kimlik: nesnenin kimliği
        return Personne.get_allowed_keys() + ["discipline"]

    # özellikler
    @property
    def discipline(self) -> str:
        return self.__discipline

    @discipline.setter
    def discipline(self, discipline: str):
        # ders, boş olmayan bir dize olmalıdır
        if Utils.is_string_ok(discipline):
            self.__discipline = discipline
        else:
            raise MyException(21, "La discipline doit être une chaîne de caractères non vide")

    # show yöntemi
    def show(self):
        print(f"Enseignant[{self.id}, {self.prénom}, {self.nom}, {self.âge}]")
    1. satır: [Enseignant] sınıfı, [Personne] sınıfını genişletir (veya türetir);
  • 18-21. satırlar: sınıfın özellik listesini tanımlar;
  • 37-38. satırlar: [show] yöntemi, öğretmenin kimliğini görüntüler;
13.2.1.2.4. [config] yapılandırması

Örnek komut dosyaları aşağıdaki [config] yapılandırmasını kullanır:


def configure():
    import os

    # yapılandırma dosyasının bulunduğu klasör
    script_dir = os.path.dirname(os.path.abspath(__file__))

    # syspath'a eklenecek klasörlerin mutlak yolları
    absolute_dependencies = [
        # BaseEntity sınıfı
        f"{script_dir}/entities",
    ]

    # syspath'ın güncellenmesi
    from myutils import set_syspath
    set_syspath(absolute_dependencies)

    # yapılandırma gerçekleştiriliyor
    return {}
  • 8-10. satırlar: projenin bağımlılıklarını içeren klasörler;
  • 14-15. satırlar: Python Path oluşturulur;
    1. satır: boş bir sözlük döndürülür (syspath yapılandırması dışında başka bir yapılandırma yoktur);
13.2.1.2.5. [fromdict_01] komut dosyası

[fromdict_01] komut dosyası şöyledir:


# uygulamayı yapılandırıyoruz
import config

config = config.configure()

# syspath yapılandırıldı - içe aktarmalar yapılabilir
from Enseignant import Enseignant

# bir öğretmen
enseignant1 = Enseignant().fromdict({"id": 1, "nom": "lourou", "prénom": "paul", "âge": 56})
enseignant1.show()
    1. satır: Bir sözlükten [Enseignant] nesnesi oluşturulur. Bunun için, sınıfın varsayılan oluşturucusu kullanılarak bir [Enseignant] nesnesi oluşturulur ve bu nesneye [fromdict] yöntemi uygulanır. Burada yürütülen [fromdict] yönteminin, üst sınıf olan [BaseEntity] sınıfına ait olduğu anlaşılmalıdır. Nitekim:
    2. [fromdict] yöntemi önce [Enseignant] sınıfında aranır. Bu yöntem mevcut değildir;
    3. ardından üst sınıf olan [Personne] sınıfında aranır. Bu yöntem mevcut değildir;
    4. ardından üst sınıf olan [BaseEntity]'te aranır. Bu sınıf mevcuttur;
    1. satır: [Enseignant] nesnesi görüntülenir;

Sonuçlar şöyledir:


C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\Scripts\python.exe C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/classes/02/fromdict_01.py
Enseignant[1, paul, lourou, 56]

Process finished with exit code 0
13.2.1.2.6. [fromdict_02] komut dosyası

[fromdict_02] betiği şöyledir:


# uygulama yapılandırılıyor
import config

config = config.configure()

# syspath yapılandırıldı - içe aktarmalar yapılabilir
from Enseignant import Enseignant

# bir öğretmen
enseignant1 = Enseignant().fromdict({"id": 1, "nom": "lourou", "prénom": "", "âge": 56})
enseignant1.show()
    1. satır: Adı boş bir öğretmen oluşturuluyor. [Personne] sınıfı boş adları kabul etmediğinden bu durum bir istisna oluşturmalıdır. Bu örnek, bir sözlük ile bir nesne arasındaki farkı göstermektedir. Nesne, özelliklerinin geçerliliğini kontrol edebilir, ancak sözlük bunu yapamaz;

Sonuçlar şöyledir:


C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\Scripts\python.exe C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/classes/02/fromdict_02.py
Traceback (most recent call last):
  File "C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/classes/02/fromdict_02.py", line 10, in <module>
    enseignant1 = Enseignant().fromdict({"id": 1, "nom": "lourou", "prénom": "", "âge": 56})
  File "C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\classes\02/entities\BaseEntity.py", line 55, in fromdict
    setattr(self, key, value)
  File "C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\classes\02/entities\Personne.py", line 42, in prénom
    raise MyException(11, "Le prénom doit être une chaîne de caractères non vide")
MyException.MyException: MyException[11, Le prénom doit être une chaîne de caractères non vide]

Process finished with exit code 1
13.2.1.2.7. [fromdict_03] komut dosyası

[fromdict_03] betiği şöyledir:


# uygulama yapılandırılıyor
import config

config = config.configure()

# syspath yapılandırıldı - içe aktarmalar yapılabilir
from Enseignant import Enseignant

# bir öğretmen
enseignant1 = Enseignant().fromdict({"id": 1, "nom": "lourou", "prénom": "albert", "âge": 56, "sexe": "M"})
enseignant1.show()
    1. satır: [Enseignant] sınıfına ait olmayan bir anahtar (cinsiyet) içeren bir sözlükten bir öğretmen oluşturuluyor. Bu durumda bir istisna atılmalıdır;

Sonuçlar şu şekildedir:


C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\Scripts\python.exe C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/classes/02/fromdict_03.py
Traceback (most recent call last):
  File "C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/classes/02/fromdict_03.py", line 10, in <module>
    enseignant1 = Enseignant().fromdict({"id": 1, "nom": "lourou", "prénom": "albert", "âge": 56, "sexe": "M"})
  File "C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\classes\02/entities\BaseEntity.py", line 51, in fromdict
    raise MyException(2, f"la clé [{key}] n'est pas autorisée")
MyException.MyException: MyException[2, la clé [sexe] n'est pas autorisée]

Process finished with exit code 1
13.2.1.2.8. [fromdict_04] komut dosyası

[fromdict_04] komut dosyası, tek bir ayrıntı dışında [fromdict_03]'in bir kopyasıdır:


# uygulama yapılandırılıyor
import config

config = config.configure()

# syspath yapılandırıldı - içe aktarmalar yapılabilir
from Enseignant import Enseignant

# bir öğretmen
enseignant1 = Enseignant().fromdict({"id": 1, "nom": "lourou", "prénom": "albert", "âge": 56, "sexe": "M"}, silent=True)
enseignant1.show()
    1. satır: [silent=True] parametresi, sözlükteki bir anahtarın [Enseignant] sınıfının bir özelliği olmaması durumunda basitçe göz ardı edilmesi gerektiğini belirtmek için kullanılmıştır. Bu durumda herhangi bir istisna atılmaz;

Sonuçlar şu şekildedir:


C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\Scripts\python.exe C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/classes/02/fromdict_04.py
Enseignant[1, albert, lourou, 56]

Process finished with exit code 0

13.2.2. [BaseEntity.asdict] yöntemi

13.2.2.1. Définition

[BaseEntity.asdict] yöntemi, anahtarları nesnenin özellikleri olan bir sözlük döndürür:


    def asdict(self, included_keys: list = None, excluded_keys: list =[]) -> dict:
        # nesnenin öznitelikleri
        attributes = self.__dict__
        # yeni öznitelikler
        new_attributes = {}
        # özellikler taranıyor
        for key, value in attributes.items():
            # anahtar açıkça isteniyorsa
            if included_keys and key in included_keys:
                self.set_value(key, value, new_attributes)
            # aksi takdirde, anahtar hariç tutulmamışsa
            elif not included_keys and key not in self.__class__.excluded_keys and key not in excluded_keys:
                self.set_value(key, value, new_attributes)
        # özellik sözlüğü döndürülür
        return new_attributes

Açıklamalar

    1. satır: [asdict] işlevi, nesnenin özelliklerini içeren sözlüğü döndürür;
  • satır 1: [included_keys]: sözlüğe eklenecek anahtarların listesi;
  • satır 1: [excluded_keys]: sözlükten çıkarılacak anahtarların listesi;
  • satır 3: [self.__dict__] özelliği, nesnenin özellik sözlüğünü döndürür. Özellik adları, sözlüğün anahtarları; değerleri ise sözlüğün değerleridir. Bir nesne, başka nesnelere referanslar içerebilir. Bu durumda özellik adlarının önüne, ait oldukları sınıfın adı eklenir. Bu, istenmeyen bir durumdur. Özelliklerin önekleri olmadan kullanılmasını istiyoruz;
    1. satır: Burada şunu anlamak gerekir ki, [asdict] işlevi [BaseEntity]'ten türetilmiş bir sınıfın içinde çalıştırılırsa, [self.__dict__] özelliği türetilmiş nesnenin özellik sözlüğünü döndürür;
    1. satır: Oluşturulacak sözlük;
    1. satır: [self.__dict__] değerleri (anahtar, değer) biçiminde taranır;
    1. satır: mevcut anahtar, dahil edilecek anahtarlar listesine aitse, birazdan açıklayacağımız [set_value] işlevi aracılığıyla [new_attributes] sözlüğüne eklenir;
    1. satır: [included_keys] parametresi mevcut değilse, [excluded_keys] parametresi kullanılır. Özellik, hariç tutulacak özellikler listesinde yer almıyorsa, [new_attributes] sözlüğüne eklenir;
    1. satır: Bir özelliği sözlükten hariç tutmanın birkaç yolu vardır:
    2. sınıf özniteliği [excluded_keys] düzeyinde tanımlanmışsa;
    3. [asdict] işlevine aktarılan [excluded_keys] listesinde tanımlanmışsa;
    4. [included_keys] parametresi mevcut ve bu özellik bu parametrede yer almıyor;
    1. satır: [new_attributes] sözlüğü döndürülür
  • ve 13. satırlardaki [set_value] işlevi şöyledir:


    @staticmethod
    def set_value(key: str, value, new_attributes: dict):
        # anahtarlar __Class__key biçiminde olabilir
        match = re.match("^.*?__(.*?)$", key)
        if match:
            # yeni anahtarı not ederiz
            newkey = match.groups()[0]
        else:
            # anahtar değişmeden kalır
            newkey = key
        # yeni anahtar sözlüğe eklenir [new_attributes]
        # gerekirse ilişkili değeri aşağıdaki türlerden birine dönüştürerek
        # dict, list, basit tür
        new_attributes[newkey] = BaseEntity.check_value(value)

Açıklamalar

    1. satır: Anahtarın __Class_key biçiminde olup olmadığına bakılır. Ana nesneye dahil olan bir nesneye aitse bu biçime sahiptir. Bu durumda, yalnızca [key] dizesi tutulur;
    1. satır: Dizgenin altını çizili son iki karakterinden sonra gelen kısmı saklıyoruz;
  • satır 8-10: anahtar __Class_key biçiminde değilse, olduğu gibi saklanır;
  • satır 11-14: [newkey] anahtarına ilişkin değer, [BaseEntity.check_value] statik yöntemi ile hesaplanır;

[BaseEntity.check_value] statik yöntemi şu şekildedir:


    @staticmethod
    def check_value(value):
        # değer, BaseEntity, list, dict veya basit bir türde olabilir
        # değer, BaseEntity türünde bir örnek mi?
        if isinstance(value, BaseEntity):
            value2 = value.asdict()
        # değer, list türünde mi?
        elif isinstance(value, list):
            value2 = BaseEntity.list2list(value)
        # değeri bir dict türünde mi?
        elif isinstance(value, dict):
            value2 = BaseEntity.dict2dict(value)
        #değeri basit bir tür mü?
        else:
            value2 = value
        # sonuç verilir
        return value2
    1. satır: [check_value] yöntemi statiktir (örnek değil, sınıf yöntemidir). Bu yöntem, sözlüğün bir anahtarına eşleştirilecek değeri parametre olarak alır:
      1. satır: Bu değer basit bir tür ise, değişmeden kalır;
    2. satır 5-6: Bu değer BaseEntity türündeyse, değer sözlüğüyle değiştirilir. Bu durumda özyinelemeli bir çağrı gerçekleşir;
    3. 8-9. satırlar: Bu değer bir liste ise, [BaseEntity.list2list] değeriyle değiştirilir;
    4. satır 11-12: Bu değer bir sözlük ise, [BaseEntity.dict2dict] değeriyle değiştirilir;

[BaseEntity.list2list] statik yöntemi şu şekildedir:


    @staticmethod
    def list2list(liste: list) -> list:
        # listenin elemanlarını inceliyoruz
        newlist = []
        for value in liste:
            newlist.append(BaseEntity.check_value(value))
        # yeni listeyi döndürüyoruz
        return newlist
    1. satır: Yöntem bir liste alır ve bir liste döndürür;
  • satır 5-6: parametre olarak alınan listenin her bir değeri, statik [BaseEntity.check_value] yöntemi tarafından döndürülen değerle değiştirilir. Dolayısıyla burada bir özyinelemeli çağrı söz konusudur. [BaseEntity.check_value] statik yöntemi, parametresi [value] basit bir tür (BaseEntity, list veya dict türü değil) olana kadar çağrılır;

[BaseEntity.dict2dict] statik yöntemi şöyledir:


    @staticmethod
    def dict2dict(dictionary: dict) -> dict:
        # sözlüğün öğelerini inceliyoruz
        newdict = {}
        for key, value in dictionary.items():
            newdict[key] = BaseEntity.check_value(value)
        # yeni sözlüğü döndürüyoruz
        return newdict
    1. satır: Yöntem bir sözlük alır ve bir sözlük döndürür;
  • 5-6. satırlar: parametre olarak alınan sözlüğün her bir değeri, statik [BaseEntity.check_value] yöntemi tarafından döndürülen değerle değiştirilir. Dolayısıyla burada bir özyinelemeli çağrı söz konusudur. [BaseEntity.check_value] statik yöntemi, parametresi [value] basit bir tür (BaseEntity, list veya dict türü değil) olana kadar çağrılır;

13.2.2.2. Exemples

[asdict_01] betiği, [asdict] yönteminin çeşitli kullanımlarını gösterir:


# uygulamayı yapılandırıyoruz
import config
config = config.configure()

# syspath yapılandırıldı - içe aktarmaları yapabiliriz
from Enseignant import Enseignant
from BaseEntity import BaseEntity

# bir öğretmen
enseignant1 = Enseignant().fromdict({"id"1"nom""lourou""prénom""paul""âge"56})
dict1 = enseignant1.asdict()
print(type(dict1))
print(enseignant1.__dict__)
print(dict1)
print(enseignant1.asdict(excluded_keys=["_Personne__âge"]))
Enseignant.excluded_keys = ["_Personne__prénom"]
print(enseignant1)
# başka bir öğretmen
enseignant2 = Enseignant().fromdict({"id"2"nom""abélard""prénom""béatrice""âge"57})
print(enseignant2.asdict())
print(enseignant2.asdict(included_keys=["_Personne__nom"]))
# bir varlık içindeki varlık listesi
Enseignant.excluded_keys = []
entity1 = BaseEntity()
enseignants = [enseignant1, enseignant2]
setattr(entity1, "enseignants", enseignants)
print(entity1.asdict())
# bir varlık içindeki varlık sözlüğü
matières = {"maths": enseignant1, "français": enseignant2}
setattr(entity1, "matières", matières)
print(entity1.asdict())

Çalıştırma sonuçları şöyledir:


C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\Scripts\python.exe C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/classes/02/asdict_01.py
<class 'dict'>
{'_BaseEntity__id': 1, '_Personne__nom': 'lourou', '_Personne__prénom': 'paul', '_Personne__âge': 56}
{'id': 1, 'nom': 'lourou', 'prénom': 'paul', 'âge': 56}
{'id': 1, 'nom': 'lourou', 'prénom': 'paul'}
{"id": 1, "nom": "lourou", "âge": 56}
{'id': 2, 'nom': 'abélard', 'âge': 57}
{'nom': 'abélard'}
{'enseignants': [{'id': 1, 'nom': 'lourou', 'prénom': 'paul', 'âge': 56}, {'id': 2, 'nom': 'abélard', 'prénom': 'béatrice', 'âge': 57}]}
{'enseignants': [{'id': 1, 'nom': 'lourou', 'prénom': 'paul', 'âge': 56}, {'id': 2, 'nom': 'abélard', 'prénom': 'béatrice', 'âge': 57}], 'matières': {'maths': {'id': 1, 'nom': 'lourou', 'prénom': 'paul', 'âge': 56}, 'français': {'id': 2, 'nom': 'abélard', 'prénom': 'béatrice', 'âge': 57}}}

Process finished with exit code 0
    1. satır, [asdict] yönteminin, [__dict__] özelliğinin kullanımına kıyasla sağladığı avantajı göstermektedir. Özelliklerin sınıf önekleri kaldırılmıştır. Bu, görüntüleme açısından daha uygundur;
  • [asdict] yöntemini kullanmanın birkaç yolu vardır:
    • tüm özellikleri istiyorsak: [asdict] yöntemini parametre olmadan kullanırız;
    • sadece belirli özellikleri istiyorsanız:
      • dahil edilecek özellikler, hariç tutulacaklardan daha fazlaysa: tek parametreli [excluded_keys] yöntemini kullanın;
      • dahil edilecek özellikler, hariç tutulacaklardan daha azsa: tek parametreli [included_keys] yöntemini kullanacağız;

13.2.3. [BaseEntity.asjson] yöntemi

Bu yöntem, bir [BaseEntity] nesnesinden veya türevinden jSON dizesini elde etmeyi sağlar. [asdict] yöntemi tarafından döndürülen sözlükten jSON dizesini görüntüler. Kodu şu şekildedir:


def asjson(self, included_keys: list = None, excluded_keys: list = []) -> str:
        # json dizesi
        return json.dumps(self.asdict(included_keys=included_keys, excluded_keys=excluded_keys), ensure_ascii=False)
    1. satır: [asjson] yönteminin parametreleri, [asdict] yönteminin parametreleriyle aynıdır;

İşte bu yöntemi kullanan bir örnek (asjson_01):


# uygulama yapılandırılıyor
import config
config = config.configure()

# syspath yapılandırıldı - artık içe aktarmalar yapılabilir
from Enseignant import Enseignant
from BaseEntity import BaseEntity

# bir öğretmen
enseignant1 = Enseignant().fromdict({"id"1"nom""lourou""prénom""paul""âge"56})
print(type(enseignant1.asjson()))
print(enseignant1.asjson(excluded_keys=["_Personne__âge"]))
Enseignant.excluded_keys = ["_Personne__prénom"]
print(enseignant1.asjson())
# başka bir öğretmen
enseignant2 = Enseignant().fromdict({"id"2"nom""abélard""prénom""béatrice""âge"57})
print(enseignant2.asjson())
print(enseignant2.asjson(included_keys=["_Personne__nom"]))
# bir varlık içindeki varlık listesi
Enseignant.excluded_keys = []
entity1 = BaseEntity()
enseignants = [enseignant1, enseignant2]
setattr(entity1, "enseignants", enseignants)
print(entity1.asjson())
# bir varlık içindeki varlık sözlüğü
matières = {"maths": enseignant1, "français": enseignant2}
setattr(entity1, "matières", matières)
print(entity1.asjson())

Sonuçlar şöyledir:


C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\Scripts\python.exe C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/classes/02/asjson_01.py
<class 'str'>
{"id": 1, "nom": "lourou", "prénom": "paul"}
{"id": 1, "nom": "lourou", "âge": 56}
{"id": 2, "nom": "abélard", "âge": 57}
{"nom": "abélard"}
{"enseignants": [{"id": 1, "nom": "lourou", "prénom": "paul", "âge": 56}, {"id": 2, "nom": "abélard", "prénom": "béatrice", "âge": 57}]}
{"enseignants": [{"id": 1, "nom": "lourou", "prénom": "paul", "âge": 56}, {"id": 2, "nom": "abélard", "prénom": "béatrice", "âge": 57}], "matières": {"maths": {"id": 1, "nom": "lourou", "prénom": "paul", "âge": 56}, "français": {"id": 2, "nom": "abélard", "prénom": "béatrice", "âge": 57}}}

Process finished with exit code 0

[BaseEntity.__str__] yöntemi, [asjson] yöntemini kullanarak [BaseEntity] nesnesinin veya türevlerinin kimliğini görüntüler:


# toString
    def __str__(self) -> str:
        return self.asjson()

13.2.4. [BaseEntity.fromjson] yöntemi

[BaseEntity.fromjson] yöntemi, bir [BaseEntity] türü nesneyi veya türevini bir jSON sözlüğünden başlatmaya olanak tanır. Kodu şöyledir:


def fromjson(self, json_state: str, silent: bool = False):
        # nesnenin durumu jSON dizesinden güncellenir
        return self.fromdict(json.loads(json_state), silent=silent)
    1. satır: Yöntem iki parametre kabul eder:
    2. [json_state]: jSON sözlüğü, [BaseEntity] nesnesini başlatmak için kullanılır;
    3. [silent]: jSON sözlüğünde, [BaseEntity] nesnesinin özelliği olarak kabul edilemeyen bir anahtarın bulunmasının bir istisna oluşturup oluşturmayacağını (silent=False) veya basitçe göz ardı edilip edilmeyeceğini (silent=True) belirtmek için;
    1. satır: Öncelikle jSON sözlüğünden bir Python sözlüğü oluşturulur, ardından [fromdict] yöntemi kullanılarak bu Python sözlüğünden [BaseEntity] nesnesi başlatılır;

İşte bir örnek (fromjson_01):


# uygulama yapılandırılır
import config

config = config.configure()

# syspath yapılandırıldı - içe aktarmalar yapılabilir
from Enseignant import Enseignant
import json

# bir öğretmen
json1 = json.dumps({"id": 1, "nom": "lourou", "prénom": "paul", "âge": 56})
enseignant1 = Enseignant().fromjson(json1)
enseignant1.show()
    1. satır: Bir sözlükten jSON dizesi oluşturulur;
    1. satır: Bu dize ile bir [Enseignant] nesnesi başlatılır;
    1. satır: öğretmen görüntülenir;

Sonuçlar şöyledir:


C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\Scripts\python.exe C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/classes/02/fromjson_01.py
Enseignant[1, paul, lourou, 56]

Process finished with exit code 0

13.2.5. [main] komut dosyası

[main] betiği, karşılaşılan farklı yöntemleri özetlemektedir:


# uygulama yapılandırılıyor
import config

config = config.configure()

# syspath yapılandırıldı - içe aktarmalar yapılabilir
from BaseEntity import BaseEntity
from MyException import MyException


# bir sınıf
class ChildEntity(BaseEntity):
    # sınıf durumundan hariç tutulan öznitelikler
    excluded_keys = []

    @staticmethod
    def get_allowed_keys():
        return ["att1", "att2", "att3", "att4"]

    @property
    def att1(self) -> int:
        return self.__att1

    @att1.setter
    def att1(self, value: int):
        if 10 >= value >= 1:
            self.__att1 = value
        else:
            raise MyException(1, f"L'attribut [att1] attend une valeur dans l'intervalle [1,10] ({value})")


# ChildEntity yapılandırması
ChildEntity.excluded_keys = []
# ChildEntity örneği
child = ChildEntity().fromdict({"att1": 1, "att2": 2})
# özellik adlarına dikkat
# [excluded_keys] ve [included_keys]'te kullanılan isimler bunlardır
print(child.__dict__)
# sınıf ön eki içermeyen özellikler
print(child)

# ChildEntity örneği
try:
    child = ChildEntity().fromdict({"att1": 1, "att5": 5})
    print(child)
except MyException as erreur:
    print(erreur)

# ChildEntity örneği
child = ChildEntity().fromdict({"att1": 1, "att2": 2, "att3": 3, "att4": 4})
print(child)

# örnek durumundan belirli anahtarların hariç tutulması
ChildEntity.excluded_keys = ['att3']
print(child)

# bir anahtar görüntülenmekten açıkça hariç tutulur
# bu anahtar, sınıf düzeyinde genel olarak hariç tutulanlara eklenir
print(child.asdict(excluded_keys=["_ChildEntity__att1"]))
print(child.asjson(excluded_keys=["att2"]))

# sınıfın sözlüğe ilişkin ilgisi
# içeriğinin geçerliliğini doğrulayabilir
try:
    child = ChildEntity().fromdict({"att1": 20})
except MyException as erreur:
    print(erreur)

# ChildEntity örneği
child1 = ChildEntity().fromdict({"att1": 1, "att2": 2, "att3": 3, "att4": 4})
# başka bir ChildEntity örneğini içeren ChildEntity örneği
child2 = ChildEntity().fromdict({"att1": 10, "att2": 20, "att3": 30, "att4": child1})
print(child2)

# included_keys, excluded_keys'e göre önceliklidir; dolayısıyla excluded_keys'ler göz ardı edilir
ChildEntity.excluded_keys = ['_ChildEntity__att1', 'att2']
print(child.asdict(included_keys=["_ChildEntity__att1", "att3"], excluded_keys=["att3", "att4"]))

Çalıştırma sonuçları şunlardır:


C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\Scripts\python.exe C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/classes/02/main.py
{'_ChildEntity__att1': 1, 'att2': 2}
{"att1": 1, "att2": 2}
MyException[2, la clé [att5] n'est pas autorisée]
{"att1": 1, "att2": 2, "att3": 3, "att4": 4}
{"att1": 1, "att2": 2, "att4": 4}
{'att2': 2, 'att4': 4}
{"att1": 1, "att4": 4}
MyException[1, L'attribut [att1] attend une valeur dans l'intervalle [1,10] (20)]
{"att1": 10, "att2": 20, "att4": {"att1": 1, "att2": 2, "att4": 4}}
{'att1': 1, 'att3': 3}

Process finished with exit code 0

Sonuçların 2. satırına dikkat edilmelidir: [ChildEntity.__dict__] özelliği (kodun 38. satırı), [included_keys] ve [excluded_keys] listelerine eklenecek özelliklerin adlarını öğrenmemizi sağlar. Yine sonuçların 2. satırında, özelliğin sınıf içinde bir getter/setter ile tanımlanmış olmasına veya bir sözlük anahtarı oluşturulur gibi oluşturulmuş olmasına bağlı olarak, [ChildEntity] sınıf adının öne eklenip eklenmediğine dikkat edilmelidir.