Qu'est-ce qu'un cas d'utilisation d'exemple pour une méthode de classe Python?
j'ai lu à quoi servent les méthodes de classe en Python? , mais les exemples dans ce post sont complexes. Je suis à la recherche d'une manière claire, simple, dépouillée exemple d'un cas d'utilisation particulier pour classmethods en Python.
pouvez-vous nommer un petit cas d'utilisation d'exemple spécifique où une méthode de classe Python serait le bon outil pour le travail?
6 réponses
méthodes d'assistance pour l'initialisation:
class MyStream(object):
@classmethod
def from_file(cls, filepath, ignore_comments=False):
with open(filepath, 'r') as fileobj:
for obj in cls(fileobj, ignore_comments):
yield obj
@classmethod
def from_socket(cls, socket, ignore_comments=False):
raise NotImplemented # Placeholder until implemented
def __init__(self, iterable, ignore_comments=False):
...
bien __new__
est une méthode de classe assez importante. C'est là où les instances viennent habituellement de
donc dict()
appels dict.__new__
bien sûr, mais il y a un autre moyen pratique de faire des dicts parfois qui est le classmethod dict.fromkeys()
par exemple.
>>> dict.fromkeys("12345")
{'1': None, '3': None, '2': None, '5': None, '4': None}
Je ne sais pas, quelque chose comme les méthodes de constructeur nommées?
class UniqueIdentifier(object):
value = 0
def __init__(self, name):
self.name = name
@classmethod
def produce(cls):
instance = cls(cls.value)
cls.value += 1
return instance
class FunkyUniqueIdentifier(UniqueIdentifier):
@classmethod
def produce(cls):
instance = super(FunkyUniqueIdentifier, cls).produce()
instance.name = "Funky %s" % instance.name
return instance
Utilisation:
>>> x = UniqueIdentifier.produce()
>>> y = FunkyUniqueIdentifier.produce()
>>> x.name
0
>>> y.name
Funky 1
je trouve que j'utilise le plus souvent @classmethod
pour associer un morceau de code à une classe, pour éviter de créer une fonction globale, pour les cas où je n'ai pas besoin d'une instance de la classe pour utiliser le code.
par exemple, je pourrais avoir une structure de données qui considère une clé valide seulement si elle est conforme à un certain modèle. Je souhaiterez peut-être utiliser ce de l'intérieur et à l'extérieur de la classe. Cependant, je ne veux pas créer encore une autre fonction globale:
def foo_key_is_valid(key):
# code for determining validity here
return valid
je préférerais regrouper CE code avec la classe à laquelle il est associé:
class Foo(object):
@classmethod
def is_valid(cls, key):
# code for determining validity here
return valid
def add_key(self, key, val):
if not Foo.is_valid(key):
raise ValueError()
..
# lets me reuse that method without an instance, and signals that
# the code is closely-associated with the Foo class
Foo.is_valid('my key')
la raison la plus importante pour utiliser un @classmethod
est dans un constructeur alternatif qui est destiné à être hérité. Cela peut être très utile dans le polymorphisme. Un exemple:
class Shape(object):
# this is an abstract class that is primarily used for inheritance defaults
# here is where you would define classmethods that can be overridden by inherited classes
@classmethod
def from_square(cls, square):
# return a default instance of cls
return cls()
notez que Shape
est une classe abstraite qui définit une méthode de classe from_square
, puisque Shape
n'est pas vraiment défini, il ne sait pas vraiment comment dériver d'une Square
donc il retourne simplement une instance par défaut de la classe.
les classes héritées sont alors autorisées à définir leurs propres versions de cette méthode:
class Square(Shape):
def __init__(self, side=10):
self.side = side
@classmethod
def from_square(cls, square):
return cls(side=square.side)
class Rectangle(Shape):
def __init__(self, length=10, width=10):
self.length = length
self.width = width
@classmethod
def from_square(cls, square):
return cls(length=square.side, width=square.side)
class RightTriangle(Shape):
def __init(self, a=10, b=10):
self.a = a
self.b = b
self.c = ((a*a) + (b*b))**(.5)
@classmethod
def from_square(cls, square):
return cls(a=square.length, b=square.width)
class Circle(Shape):
def __init__(self, radius=10):
self.radius = radius
@classmethod
def from_square(cls, square):
return cls(radius=square.length/2)
l'usage vous permet de traiter toutes ces classes non fondées polymorphiquement
square = Square(3)
for polymorphic_class in (Square, Rectangle, RightTriangle, Circle):
this_shape = polymorphic_class.from_square(square)
tout cela est très bien et épatant, pourriez-vous dire, mais pourquoi ne pourrais-je pas utiliser comme @staticmethod
pour accomplir ce même comportement polymorphe:
class Circle(Shape):
def __init__(self, radius=10):
self.radius = radius
@staticmethod
def from_square(square):
return Circle(radius=square.length/2)
La réponse est que vous pouvez, mais vous n'obtenez pas l' avantages de l'héritage parce que Circle
doit être appelé explicitement dans la méthode. Ce qui veut dire que si je l'appelle d'une classe héritée sans passer, j'obtiendrais toujours Circle
à chaque fois.
notez ce qui est gagné quand je définit une autre classe de forme qui n'a pas vraiment de logique de_square personnalisée:
class Hexagon(Shape):
def __init__(self, side=10):
self.side = side
# note the absence of classmethod here, this will use from_square it inherits from shape
ici, vous pouvez laisser le @classmethod
indéfini et il utilisera la logique de Shape.from_square
tandis que retenir cls
de l'OMS et retourner la forme appropriée.
square = Square(3)
for polymorphic_class in (Square, Rectangle, RightTriangle, Circle, Hexagon):
this_shape = polymorphic_class.from_square(square)
in class MyClass(object):
'''
classdocs
'''
obj=0
x=classmethod
def __init__(self):
'''
Constructor
'''
self.nom='lamaizi'
self.prenom='anas'
self.age=21
self.ville='Casablanca'
if __name__:
ob=MyClass()
print(ob.nom)
print(ob.prenom)
print(ob.age)
print(ob.ville)