@classmetod benzeyicisi gerçekten gerekli mi?

Sınıf metodları dersini daha yeni birtirdim ve sınıf metodlarını kullanmam için @classmetod benzeyiciyi kullanmak gerektiğini öğrendim.

class Çalışan():
    personel = []

    def __init__(self,isim):
        self.isim = isim
        self.kabiliyetleri = []
        self.personel_ekle()

    def personel_ekle(self):
        Çalışan.personel.append(self.isim)
        print('{} adlı kişi personele eklendi'.format(self.isim))
    
    def personeli_görüntüle():
        for i in Çalışan.personel:
            print(i)

Şeklinde personeli_görüntüle fonksiyonunu oluşturdum ve

Çalışan.personeli_görüntüle()

yazarak kullanabiliyorum

personeli_görüntüle fonksiyonunu, Çalışan sınıfını kullanarak çağırabiliyorsunuz. Ama bu sınıftan oluşturacağınız örnekler, personeli_görüntüle fonksiyonunu çağıramayacaklardır.

c = Çalışan(isim="hello")
Çalışan.personeli_görüntüle()
c.personeli_görüntüle()  # <-- Hata yükseltecek.

Ama, classmethod bezeyicisini eklerseniz, bu fonksiyona örnek üzerinden de ulaşabilirsiniz:

    @classmethod
    def personeli_görüntüle(cls):
        for i in cls.personel:
            print(i)
c = Çalışan(isim="hello")
Çalışan.personeli_görüntüle()
c.personeli_görüntüle()  # <-- Artık hata yükseltmez.

1 yıldır pythonla çalışıyorum. hala bu classmethod olayını tam kavrayamadım. birçok makale okudum ama sanırım bazı konularda eksiğim olduğu için anlayamıyorum. burada classmethod wrapper kullanmadan sadece methoda self verip geçsek de aynı şeyi yapabiliyoruz. aralarındaki farkı açıklayabilir misiniz?

edit: yine yazbelde yazılan başka bir yorumdan anladım durumu. sorum çözüldü teşekkürler.

@dildeolupbiten’in bahsettigi temel sebepler disinda, @classmethod'in varliginin sebebi OOP kurallarinda var olmasi.

Genelde buralarda ornek verirken Insan diye sinif olusturup isim, yas gibi ozellikler eklerler ama bu sefer gercek bir ornek verecegim:

from dataclasses import dataclass
from typing import Optional
from enum import Enum
from pathlib import Path
import random


class FileFormat(Enum):
    JPEG = "JPEG"
    PNG  = "PNG"
    ZIP  = "ZIP"


@dataclass
class File:
    filename: str
    content: bytes
    format: Optional[FileFormat]

    @classmethod
    def new_from_path(cls, path: Path):
        content = path.read_bytes()
        return cls(
            filename=path.name,
            content=content,
            format=File.detect_format(content)
        )

    @staticmethod
    def detect_format(content: bytes) -> FileFormat:
        ...
        return random.choice([FileFormat.JPEG, FileFormat.PNG, FileFormat.ZIP])

Dosyayi temsil eden File sinifimiz var. Klasik bir sekilde instance olusturularak kullabilabilir:

File("hello.png", bytes(), FileFormat.PNG)

Ama dosya yolu alan, kalan seyleri dosyayi okuyup otomatik dolduran bir fonksiyona ihtiyac duyabiliriz. Bu durumda classmethod kullaniriz.

File.new_from_path(Path("/path/to/hello.png"))
# File("hello.png", b'PNG...', FileFormat.PNG)

Ya da ne direkt olarak File sinifiyla ne de File instance’lariyla alakasi olmayan, ama File namespace’i icinde bulunmasinin uygun olacagi durumlarda @staticmethod kullanabiliriz:

with open("hello.png", "rb") as f:
    File.detect_format(f.read())
    # FileFormat.PNG

Bu kod cok iyi bir ornek oldu classmethod ve staticmethod konusunda kafa karisikliklarina. Wiki yapma ozelligi vardi eskiden ama su anda bulamadim, olsa cok iyi olurmus.

3 Beğeni