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 ?
Réponses
Trop de publicités?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")
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)
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.
- Réponses précédentes
- Plus de réponses
9 votes
Il n'y a pas de notion de méthodes privées vs publiques en Python.
10 votes
Python n'est pas Java.
8 votes
@Tadeck, s'il vous plaît arrêtez de corriger à tort les gens. Dénaturer un nom ne le rend pas privé.
10 votes
@DanielRoseman: larsmans a dit "il n'y a pas de notion de méthodes privées vs publiques en Python". Je dis qu'il a tort. Documentation dit: "Puisqu'il y a un cas d'utilisation valide pour les membres privés de la classe (...), il y a un support limité pour un tel mécanisme, appelé embrouillage de noms.". Veuillez arrêter de débattre sans prouver que vous avez raison.
2 votes
@Tadeck, répétant ma réponse : une méthode marquée avec
__
peut toujours être appelée commeobj._ClassName__Method()
. Maintenant, pourriez-vous expliquer comment cela est privé ?4 votes
@BasicWolf: Veuillez lire pleinement mon commentaire en premier. Le mélange de noms vous donne une notion (partielle) des classes privées. Veuillez ne pas dire que l'appel de
obj._ClassName__Method()
en dehors deClassName
est un comportement correct.