Каков пример использования для Python classmethod?
Я читал для чего существуют методы класса в Python? но примеры в этом посте сложные. Я ищу ясный, простой, голый пример конкретного варианта использования для classmethods в Python.
можете ли вы назвать небольшой конкретный пример использования, где Python classmethod будет правильным инструментом для задания?
6 ответов
вспомогательные методы для инициализации:
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):
...
хорошо __new__
является довольно важным classmethod. Это где экземпляры обычно приходят из
так dict()
звонки dict.__new__
конечно, но есть еще один удобный способ сделать диктовки иногда, который является classmethod dict.fromkeys()
например.
>>> dict.fromkeys("12345")
{'1': None, '3': None, '2': None, '5': None, '4': None}
Я не знаю, что-то вроде названные методы конструктор?
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
использование:
>>> x = UniqueIdentifier.produce()
>>> y = FunkyUniqueIdentifier.produce()
>>> x.name
0
>>> y.name
Funky 1
Я нахожу, что я чаще всего использую @classmethod
чтобы связать фрагмент кода с классом, чтобы избежать создания глобальной функции, для случаев, когда мне не требуется экземпляр класса для использования кода.
например, у меня может быть структура данных, которая считает ключ действительным, только если он соответствует некоторому шаблону. Возможно, я захочу использовать это внутри и вне класса. Однако я не хочу создавать еще одну глобальную функцию:
def foo_key_is_valid(key):
# code for determining validity here
return valid
Я бы предпочел группу этот код с классом, с которым он связан:
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')
самая большая причина для использования @classmethod
в другой конструктор, который предназначен для наследования. Это может быть очень полезно в полиморфизме. Пример:
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()
обратите внимание, что Shape
является абстрактным классом, который определяет classmethod from_square
С Shape
на самом деле не определен, он действительно не знает, как вывести себя из Square
поэтому он просто возвращает экземпляр класса по умолчанию.
наследуемые классы затем можно определить их собственные версии этого метода:
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)
использование позволяет обрабатывать все эти удаленные классы полиморфно
square = Square(3)
for polymorphic_class in (Square, Rectangle, RightTriangle, Circle):
this_shape = polymorphic_class.from_square(square)
это все хорошо и денди вы могли бы сказать, но почему я не мог просто использовать как @staticmethod
чтобы выполнить то же самое полиморфное поведение:
class Circle(Shape):
def __init__(self, radius=10):
self.radius = radius
@staticmethod
def from_square(square):
return Circle(radius=square.length/2)
ответ заключается в том, что вы могли бы, но вы не получаете преимущества наследования, потому что Circle
должен быть вызван явно в методе. В смысле, если я назову это из унаследованного класса без переопределения я все равно получу Circle
каждый раз.
обратите внимание, что получается, когда я определяю другой класс формы, который на самом деле не имеет никакой пользовательской логики from_square:
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
здесь вы можете оставить @classmethod
undefined и он будет использовать логику из Shape.from_square
при сохранении, кто cls
is и возвращает соответствующую форму.
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)