92 votes

Constructeur privé en Python

Comment créer un constructeur privé qui ne doit être appelé que par la fonction statique de la classe et non par un autre endroit ?

9 votes

Il n'y a pas de notion de méthodes privées vs publiques en Python.

10 votes

8 votes

@Tadeck, s'il vous plaît arrêtez de corriger à tort les gens. Dénaturer un nom ne le rend pas privé.

1voto

PIYUSH JIIT Points 61

Je sais, je suis en retard mais nous pouvons faire quelque chose comme ça pour créer un constructeur privé.

class MyClass:
    __instance = None
    __private = False

    @staticmethod
    def get_instance():

        MyClass.__private = True
        __instance = MyClass()
        MyClass.__private = False
        return MyClass.__instance

    def __init__(self):

        if MyClass.__private == False:
             raise Exception("C'est une méthode privée. Veuillez utiliser la méthode get_instance")

1voto

Pascal T. Points 1376

Une autre solution consiste à laisser __init__ demander une sorte de secret privé que seuls les méthodes de fabrique connaîtront.

Voir l'exemple ci-dessous:

from __future__ import annotations

class Foo:
    name: str

    def __init__(self, check_private_constructor: str):
        if check_private_constructor != "from_within":
            raise RuntimeError("Veuillez utiliser des constructeurs nommés!")

    @staticmethod
    def from_name(name: str) -> Foo:
        r = Foo("from_within")
        r.name = name
        return r

    @staticmethod
    def from_index(index: int) -> Foo:
        r = Foo("from_within")
        r.name = str(index)
        return r

    def __str__(self):
        return "Foo.name=" + self.name

# a = Foo("eee")    # lèvera une exception
a = Foo.from_name("Bob")
print(a)
b = Foo.from_index(3)
print(b)

0voto

Joel Berkeley Points 1532

Une solution claire et légère consiste à rendre les arguments du constructeur obligatoires mais "privés". Cela ne fonctionne vraiment que si vous les spécifiez également par mot-clé, sinon il est trop facile de les manquer

class Foo:
    def __init__(self, *, _x: int):
        self._x = _x

    @classmethod
    def create(cls, x: int) -> Foo:
        return Foo(_x=x)

Ici, Foo(_x=1) indique que nous utilisons mal l'API.

La question de savoir si Foo(_x=x) dans create enfreint le contrat de la classe est discutable. Je suis indécis.

-2voto

BaiJiFeiLong Points 498
class MongoConn(object):
    @classmethod
    def instance(cls):
        if not hasattr(cls, '_instance'):
            cls._instance = cls()
        return cls._instance

    def __init__(self):
        assert not hasattr(self.__class__, '_instance'), 'Ne pas appeler le constructeur directement!'

Si vous voulez une seule instance.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X