Каков пример использования метода класса Python? - PullRequest
58 голосов
/ 21 апреля 2011

Я прочитал Для чего нужны методы класса в Python? , но примеры в этом посте сложны. Я ищу ясный, простой, простой пример конкретного варианта использования методов класса в Python.

Можете ли вы назвать небольшой конкретный пример использования, где метод класса Python будет подходящим инструментом для работы?

Ответы [ 6 ]

46 голосов
/ 21 апреля 2011

Вспомогательные методы для инициализации:

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):
       ...
28 голосов
/ 21 апреля 2011

Ну, __new__ - довольно важный метод класса. Это то место, откуда обычно приходят экземпляры

так что dict() звонит dict.__new__ конечно, но есть и другой удобный способ делать диктовки иногда, это метод класса dict.fromkeys()

например.

>>> dict.fromkeys("12345")
{'1': None, '3': None, '2': None, '5': None, '4': None}
18 голосов
/ 21 апреля 2011

Не знаю, что-то вроде именованных методов конструктора?

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
10 голосов
/ 17 июля 2017

Основная причина использования @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 является абстрактным классом, который определяет метод 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 неопределенным, и он будет использовать логикуот Shape.from_square, сохраняя cls и возвращая соответствующую форму.

square = Square(3)
for polymorphic_class in (Square, Rectangle, RightTriangle, Circle, Hexagon):
    this_shape = polymorphic_class.from_square(square)
10 голосов
/ 21 апреля 2011

Я считаю, что чаще всего я использую @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')
0 голосов
/ 09 февраля 2015
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)
...