Klasy Python z tylko jedną instancją: Kiedy utworzyć (pojedynczą) instancję klasy, a kiedy zamiast tego pracować z klasą?

11

Biorąc pod uwagę klasę Python, która zostanie utworzona tylko raz, tzn. Będzie tylko jeden obiekt klasy. Zastanawiałem się, w jakich przypadkach sensowne jest utworzenie instancji pojedynczej klasy zamiast pracy bezpośrednio z klasą.

Jest podobne pytanie , ale koncentruje się na innym:

  1. chodzi o grupowanie zmiennych globalnych i funkcji w klasę i
  2. Nie jest on specyficzny dla Pythona. To ostatnie oznacza, że ​​nie uwzględnia faktu, że klasy (w języku Python) są również obiektami.

AKTUALIZACJA:

W Pythonie mogę wykonywać następujące czynności zarówno z klasami, jak i obiektami:

class A(object):
    pass

A.some_state_var = True
# Then later
A.some_state_var = False


my_a = A()

my_a.some_state_var = True
# Then later
my_a.some_state_var = False

Nie rozumiem więc, jak wybór między klasą a instancją tej klasy dotyczy stanu (w Pythonie). Mogę utrzymać stan z jednym z dwóch.

Co więcej, motywacja do stworzenia mojej klasy / instancji klasy nie polega na egzekwowaniu wymogu Singleton.

Nie chodzi też o tworzenie nowego typu.

Motywacją jest zgrupowanie powiązanych kodów i danych oraz posiadanie interfejsu. Dlatego początkowo zamodelowałem go jako klasę na schemacie klas. Dopiero przy implementacji zacząłem się zastanawiać, czy utworzyć tę klasę, czy nie.

langlauf.io
źródło

Odpowiedzi:

16

Biorąc pod uwagę klasę Python, która zostanie utworzona tylko raz, tzn. Będzie tylko jeden obiekt klasy. Zastanawiałem się, w jakich przypadkach sensowne jest utworzenie instancji pojedynczej klasy zamiast pracy bezpośrednio z klasą.

Więc to jest to:

class Singleton:
    '''don't bother instantiating me'''
    clsvar1 = 'foo'

    @classmethod
    def foobar(cls, *args, **kwargs):
        if condition():
            cls.clsvar1 = 'bar'

kontra to?

class Singleton:
    '''instantiate and use me'''
    def __init__(self):
        self.var1 = 'foo'

    def foobar(self, *args, **kwargs):
        if condition():
            self.var1 = 'bar'

Rekomendacje

Zdecydowanie wolałbym ten, który ma zostać utworzony. Kiedy tworzysz „typ rzeczy”, co oznacza, że ​​tworzysz rzeczy tego typu.

Motywacją jest zgrupowanie powiązanych kodów i danych oraz posiadanie interfejsu.

To powiedziawszy, dlaczego nie skorzystać z modułu, ponieważ wszystko czego potrzebujesz to przestrzeń nazw? Moduły są singletonami, kodem i danymi związanymi z grupą, a to jest nieco prostsze i prawdopodobnie byłoby uważane za bardziej Pythonic:

var1 ='foo'

def foobar(*args, **kwargs):
    global var1
    if condition():
        var1 = 'bar'

Zatem użycie byłoby zamiast:

from modules.singleton import Singleton
Singleton.foobar()

lub

from modules.singleton import Singleton
the_singleton = Singleton()
the_singleton.foobar()

Zrób to:

from modules import singleton
singleton.foobar()
Aaron Hall
źródło
3
Dziękuję za odpowiedź. Czy naprawdę sugerowałbyś utworzenie nowego modułu (nowego pliku .py) dla każdej funkcji (łącznie ze zmiennymi)? Może to spowodować powstanie wielu małych plików .py. Czy zgrupowałbyś wszystkie (przynajmniej w jakiś sposób powiązane) funkcje i zmienne „bezklasowe” w jednym module?
langlauf.io,
Jeszcze jedna uwaga: piszesz „ponieważ wszystko czego potrzebujesz to przestrzeń nazw”. Chcę zgrupować powiązany kod, tj. Funkcje i dane, w jednym miejscu i mieć do niego interfejs. Nie chodzi o tworzenie „Typu”. Zresztą podczas projektowania to i tak da klasę na schemacie klas, prawda?
langlauf.io,
2

Zastanawiałem się, w jakich przypadkach sensowne jest utworzenie instancji pojedynczej klasy zamiast pracy bezpośrednio z klasą.

Jest to jedna z tych rzeczy, które spowodują wojnę religijną, jeśli wplątujesz się w nią zbyt wiele.

Ale ogólnie praktyką, którą widziałem wiele razy, jest to, że metody klasowe powinny zajmować się tylko tworzeniem instancji tej klasy.

Jeśli myślisz o tym, czym jest klasa, jaki jest jej cel / zachowanie, to ma to sens. Celem klasy jest tworzenie instancji obiektów opartych na niej . Jest to plan, który może również budować budynek. Klasa „User” tworzy obiekty „user”. Klasa „Pies” tworzy obiekty „pies” itp

Podaj, że zachowanie klasy ma sens, dlatego metody, które dodasz do klasy „X”, zajmą się tworzeniem obiektów „x”.

Więc nawet jeśli kiedykolwiek będziesz potrzebować tylko jednego obiektu „x”, powinieneś go zaimplementować.

Dodanie metod do klasy X, które nie są związane z tworzeniem instancji obiektów „x”, może prowadzić do mylenia nieoczekiwanego kodu. Istnieje oczywiście mnóstwo przykładów w prawdziwym świecie, w którym ludzie i tak to zrobili, ale tak jak powiedziałem, ta ścieżka prowadzi do wojny religijnej.

Cormac Mulhall
źródło