В чем разница между функцией, украшенной @staticmethod, и одной, украшенной с @classmethod?

4176
Daryl Spitzer 26 Сен 2008 в 01:01

22 ответа

Лучший ответ

Может быть, пример кода поможет: обратите внимание на разницу в сигнатурах вызовов foo, class_foo и static_foo:

class A(object):
    def foo(self, x):
        print "executing foo(%s, %s)" % (self, x)

    @classmethod
    def class_foo(cls, x):
        print "executing class_foo(%s, %s)" % (cls, x)

    @staticmethod
    def static_foo(x):
        print "executing static_foo(%s)" % x    

a = A()

Ниже приведен обычный способ вызова экземпляра объекта методом. Экземпляр объекта a неявно передается в качестве первого аргумента.

a.foo(1)
# executing foo(<__main__.A object at 0xb7dbef0c>,1)

При использовании методов класса класс экземпляра объекта неявно передается в качестве первого аргумента вместо self.

a.class_foo(1)
# executing class_foo(<class '__main__.A'>,1)

Вы также можете вызвать class_foo, используя класс. На самом деле, если вы определите что-то, чтобы быть метод класса, это, вероятно, потому, что вы собираетесь вызывать его из класса, а не из экземпляра класса. A.foo(1) вызвал бы ошибку TypeError, но A.class_foo(1) прекрасно работает:

A.class_foo(1)
# executing class_foo(<class '__main__.A'>,1)

Один из способов использования методов класса - создание наследуемых альтернативных конструкторов.


При использовании статических методов ни self (экземпляр объекта), ни cls (класс) неявно передаются в качестве первого аргумента. Они ведут себя как простые функции, за исключением того, что вы можете вызывать их из экземпляра или класса:

a.static_foo(1)
# executing static_foo(1)

A.static_foo('hi')
# executing static_foo(hi)

Статические методы используются для группировки функций, которые имеют некоторую логическую связь с классом для класса.


foo это просто функция, но когда вы вызываете a.foo, вы не просто получаете функцию, вы получаете «частично примененную» версию функции с экземпляром объекта a, связанным в качестве первого аргумента функции. foo ожидает 2 аргумента, а a.foo ожидает только 1 аргумент.

a связан с foo. Вот что подразумевается под термином «связанный» ниже:

print(a.foo)
# <bound method A.foo of <__main__.A object at 0xb7d52f0c>>

С a.class_foo a не связан с class_foo, скорее класс A связан с class_foo.

print(a.class_foo)
# <bound method type.class_foo of <class '__main__.A'>>

Здесь со статическим методом, даже если это метод, a.static_foo просто возвращает хорошая функция ole без привязки аргументов. static_foo ожидает 1 аргумент и a.static_foo также ожидает 1 аргумент.

print(a.static_foo)
# <function static_foo at 0xb7d479cc>

И, конечно, то же самое происходит, когда вы вызываете static_foo с классом A.

print(A.static_foo)
# <function static_foo at 0xb7d479cc>
3051
sigjuice 1 Мар 2019 в 18:34

Официальные документы по питону:

@classmethod

Метод класса получает класс как неявный первый аргумент, так же, как метод экземпляра получает экземпляр. Чтобы объявить метод класса, используйте эту идиому:

class C:
    @classmethod
    def f(cls, arg1, arg2, ...): ... 

Форма @classmethod является функцией декоратор - см. описание определения функций в функции определения для подробностей.

Это может быть вызвано либо в классе (например, C.f()) или в экземпляре (например, C().f()). Экземпляр игнорируется за исключением его класса. Если метод класса вызывается для производного класс, объект производного класса принят в качестве подразумеваемого первого аргумента.

Методы класса отличаются от C ++ или статические методы Java. Если хочешь см. staticmethod() в этом раздел.

@staticmethod

Статический метод не получает неявный первый аргумент. Чтобы объявить статический метод, используйте эту идиому:

class C:
    @staticmethod
    def f(arg1, arg2, ...): ... 

Форма @staticmethod является функцией декоратор - см. описание определения функций в функции определения для подробностей.

Это может быть вызвано либо в классе (например, C.f()) или в экземпляре (например, C().f()). Экземпляр игнорируется за исключением его класса.

Статические методы в Python похожи к найденным в Java или C ++. Для более продвинутая концепция, см. classmethod() в этом разделе.

102
me_and 11 Дек 2012 в 09:56

В основном @classmethod создает метод, первым аргументом которого является класс, из которого он вызывается (а не экземпляр класса), @staticmethod не имеет никаких неявных аргументов.

141
Tadeck 8 Окт 2012 в 02:07

Быстрый взлом других идентичных методов в iPython показывает, что @staticmethod дает незначительный прирост производительности (в наносекундах), но в остальном он, похоже, не выполняет никакой функции. Кроме того, любое повышение производительности, вероятно, будет устранено дополнительной работой по обработке метода с помощью staticmethod() во время компиляции (что происходит до выполнения любого кода при запуске сценария).

Ради читабельности кода я бы избегал @staticmethod, если только ваш метод не будет использоваться для больших нагрузок, где подсчитываются наносекунды.

-5
Keith Pinson 17 Дек 2012 в 19:10

Мой вклад демонстрирует разницу между @classmethod, @staticmethod и методами экземпляра, включая то, как экземпляр может косвенно вызывать @staticmethod. Но вместо косвенного вызова @staticmethod из экземпляра, сделать его частным может быть более "питонным". Получение чего-то из закрытого метода здесь не демонстрируется, но в основном это та же концепция.

#!python3

from os import system
system('cls')
# %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %

class DemoClass(object):
    # instance methods need a class instance and
    # can access the instance through 'self'
    def instance_method_1(self):
        return 'called from inside the instance_method_1()'

    def instance_method_2(self):
        # an instance outside the class indirectly calls the static_method
        return self.static_method() + ' via instance_method_2()'

    # class methods don't need a class instance, they can't access the
    # instance (self) but they have access to the class itself via 'cls'
    @classmethod
    def class_method(cls):
        return 'called from inside the class_method()'

    # static methods don't have access to 'cls' or 'self', they work like
    # regular functions but belong to the class' namespace
    @staticmethod
    def static_method():
        return 'called from inside the static_method()'
# %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %

# works even if the class hasn't been instantiated
print(DemoClass.class_method() + '\n')
''' called from inside the class_method() '''

# works even if the class hasn't been instantiated
print(DemoClass.static_method() + '\n')
''' called from inside the static_method() '''
# %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %

# >>>>> all methods types can be called on a class instance <<<<<
# instantiate the class
democlassObj = DemoClass()

# call instance_method_1()
print(democlassObj.instance_method_1() + '\n')
''' called from inside the instance_method_1() '''

# # indirectly call static_method through instance_method_2(), there's really no use
# for this since a @staticmethod can be called whether the class has been
# instantiated or not
print(democlassObj.instance_method_2() + '\n')
''' called from inside the static_method() via instance_method_2() '''

# call class_method()
print(democlassObj.class_method() + '\n')
'''  called from inside the class_method() '''

# call static_method()
print(democlassObj.static_method())
''' called from inside the static_method() '''

"""
# whether the class is instantiated or not, this doesn't work
print(DemoClass.instance_method_1() + '\n')
'''
TypeError: TypeError: unbound method instancemethod() must be called with
DemoClass instance as first argument (got nothing instead)
'''
"""
4
Michael Swartz 25 Июн 2018 в 02:38

@classmethod: может использоваться для создания общего глобального доступа ко всем экземплярам, созданным в этом классе ..... например, при обновлении записи несколькими пользователями .... В частности, я обнаружил, что это полезно при создании синглетонов ...: )

Метод @static: не имеет ничего общего с классом или экземпляром, связанным с ... но для удобства чтения можно использовать статический метод

7
vijay 20 Сен 2017 в 17:07

@staticmethod просто отключает функцию по умолчанию как дескриптор метода. classmethod оборачивает вашу функцию в вызываемый контейнер, который передает ссылку на собственный класс в качестве первого аргумента:

>>> class C(object):
...  pass
... 
>>> def f():
...  pass
... 
>>> staticmethod(f).__get__(None, C)
<function f at 0x5c1cf0>
>>> classmethod(f).__get__(None, C)
<bound method type.f of <class '__main__.C'>>

На самом деле, classmethod имеет накладные расходы времени выполнения, но позволяет получить доступ к классу-владельцу. В качестве альтернативы я рекомендую использовать метакласс и поместить методы класса в этот метакласс:

>>> class CMeta(type):
...  def foo(cls):
...   print cls
... 
>>> class C(object):
...  __metaclass__ = CMeta
... 
>>> C.foo()
<class '__main__.C'>
21
Armin Ronacher 25 Сен 2008 в 21:24

Чтобы решить, использовать ли @staticmethod или @ classmethod вы должны заглянуть внутрь своего метода. Если ваш метод обращается к другим переменным / методам в вашем классе, используйте @classmethod . С другой стороны, если ваш метод не касается других частей класса, используйте @staticmethod.

class Apple:

    _counter = 0

    @staticmethod
    def about_apple():
        print('Apple is good for you.')

        # note you can still access other member of the class
        # but you have to use the class instance 
        # which is not very nice, because you have repeat yourself
        # 
        # For example:
        # @staticmethod
        #    print('Number of apples have been juiced: %s' % Apple._counter)
        #
        # @classmethod
        #    print('Number of apples have been juiced: %s' % cls._counter)
        #
        #    @classmethod is especially useful when you move your function to other class,
        #       you don't have to rename the class reference 

    @classmethod
    def make_apple_juice(cls, number_of_apples):
        print('Make juice:')
        for i in range(number_of_apples):
            cls._juice_this(i)

    @classmethod
    def _juice_this(cls, apple):
        print('Juicing %d...' % apple)
        cls._counter += 1
65
Du D. 5 Фев 2018 в 14:45

Я думаю, что предоставление чисто Python-версии staticmethod и classmethod поможет понять разницу между ними на уровне языка.

Оба они не являются дескрипторами данных (было бы легче понять их, если вы знакомы с сначала дескрипторы).

class StaticMethod(object):
    "Emulate PyStaticMethod_Type() in Objects/funcobject.c"

    def __init__(self, f):
        self.f = f

    def __get__(self, obj, objtype=None):
        return self.f


class ClassMethod(object):
    "Emulate PyClassMethod_Type() in Objects/funcobject.c"
    def __init__(self, f):
        self.f = f

    def __get__(self, obj, cls=None):
        def inner(*args, **kwargs):
            if cls is None:
                cls = type(obj)
            return self.f(cls, *args, **kwargs)
        return inner
2
Jacky 20 Ноя 2019 в 09:50

Вы можете рассмотреть разницу между:

Class A:
    def foo():  # no self parameter, no decorator
        pass

И

Class B:
    @staticmethod
    def foo():  # no self parameter
        pass

Это изменилось между python2 и python3:

Python2 :

>>> A.foo()
TypeError
>>> A().foo()
TypeError
>>> B.foo()
>>> B().foo()

Python3 :

>>> A.foo()
>>> A().foo()
TypeError
>>> B.foo()
>>> B().foo()

Поэтому использование @staticmethod для методов, вызываемых только из класса, стало необязательным в python3. Если вы хотите вызывать их как из класса, так и из экземпляра, вам все равно нужно использовать декоратор @staticmethod.

Другие случаи были хорошо охвачены ответом unutbus.

4
David Nathan 24 Янв 2019 в 12:56

Еще одно соображение относительно статического метода по сравнению с классическим методом связано с наследованием. Скажем, у вас есть следующий класс:

class Foo(object):
    @staticmethod
    def bar():
        return "In Foo"

И затем вы хотите переопределить bar() в дочернем классе:

class Foo2(Foo):
    @staticmethod
    def bar():
        return "In Foo2"

Это работает, но обратите внимание, что теперь реализация bar() в дочернем классе (Foo2) больше не может использовать в своих интересах что-то определенное для этого класса. Например, скажем, Foo2 имел метод magic(), который вы хотите использовать в Foo2 реализации bar():

class Foo2(Foo):
    @staticmethod
    def bar():
        return "In Foo2"
    @staticmethod
    def magic():
        return "Something useful you'd like to use in bar, but now can't" 

Обходной путь здесь будет заключаться в том, чтобы вызвать Foo2.magic() в bar(), но затем вы повторяете себя (если имя Foo2 изменится, вы должны будете не забыть обновить это {{X3] }} метод).

Для меня это небольшое нарушение принципа открытия / закрытия, поскольку решение принято в Foo влияет на вашу способность к рефакторингу общего кода в производном классе (то есть он менее открыт для расширения). Если бы bar() был classmethod, мы были бы в порядке:

class Foo(object):
    @classmethod
    def bar(cls):
        return "In Foo"

class Foo2(Foo):
    @classmethod
    def bar(cls):
        return "In Foo2 " + cls.magic()
    @classmethod
    def magic(cls):
        return "MAGIC"

print Foo2().bar()

Дает: In Foo2 MAGIC

12
Adam Parkin 4 Окт 2016 в 16:09

Метод класса получает класс как неявный первый аргумент, так же, как метод экземпляра получает экземпляр. Это метод, который привязан к классу, а не к объекту класса. Он имеет доступ к состоянию класса, так как принимает параметр класса, который указывает на класс, а не на экземпляр объекта. Он может изменять состояние класса, которое будет применяться ко всем экземплярам класса. Например, он может изменить переменную класса, которая будет применима ко всем экземплярам.

С другой стороны, статический метод не получает неявный первый аргумент по сравнению с методами класса или методами экземпляра. И не может получить доступ или изменить состояние класса. Он принадлежит только классу, потому что с точки зрения дизайна это правильный путь. Но с точки зрения функциональности не связан, во время выполнения, с классом.

В качестве руководства используйте статические методы в качестве утилит, используйте методы класса, например, как фабрику. Или, может быть, определить синглтон. И используйте методы экземпляров для моделирования состояния и поведения экземпляров.

Надеюсь, мне было ясно!

3
Nicolae Petridean 20 Ноя 2019 в 11:48

Я попытаюсь объяснить основную разницу на примере.

class A(object):
    x = 0

    def say_hi(self):
        pass

    @staticmethod
    def say_hi_static():
        pass

    @classmethod
    def say_hi_class(cls):
        pass

    def run_self(self):
        self.x += 1
        print self.x # outputs 1
        self.say_hi()
        self.say_hi_static()
        self.say_hi_class()

    @staticmethod
    def run_static():
        print A.x  # outputs 0
        # A.say_hi() #  wrong
        A.say_hi_static()
        A.say_hi_class()

    @classmethod
    def run_class(cls):
        print cls.x # outputs 0
        # cls.say_hi() #  wrong
        cls.say_hi_static()
        cls.say_hi_class()

1 - мы можем напрямую вызывать static и classmethods без инициализации

# A.run_self() #  wrong
A.run_static()
A.run_class()

2- Статический метод не может вызывать метод self, но может вызывать другой статический метод и метод класса

3- Статический метод принадлежит классу и не будет использовать объект вообще.

4- Метод класса связан не с объектом, а с классом.

8
Rizwan Mumtaz 20 Сен 2016 в 09:03

Я думаю, что лучший вопрос: "Когда бы вы использовали @classmethod против @staticmethod?"

@classmethod позволяет вам легко получить доступ к закрытым членам, связанным с определением класса. это отличный способ создавать синглтоны или фабричные классы, которые контролируют количество экземпляров созданных объектов.

@staticmethod обеспечивает предельный прирост производительности, но мне еще предстоит увидеть продуктивное использование статического метода в классе, который не может быть реализован как отдельная функция вне класса.

29
Nathan Tregillus 19 Май 2015 в 15:27

Методы класса, как следует из названия, используются для внесения изменений в классы, а не в объекты. Чтобы внести изменения в классы, они изменят атрибуты класса (не атрибуты объекта), поскольку именно так вы обновляете классы. По этой причине методы класса принимают класс (условно обозначаемый как «cls») в качестве первого аргумента.

class A(object):
    m=54

    @classmethod
    def class_method(cls):
        print "m is %d" % cls.m

Статические методы, с другой стороны, используются для выполнения функций, которые не связаны с классом, то есть они не будут читать или записывать переменные класса. Следовательно, статические методы не принимают классы в качестве аргументов. Они используются для того, чтобы классы могли выполнять функции, которые не имеют прямого отношения к назначению класса.

class X(object):
    m=54 #will not be referenced

    @staticmethod
    def static_method():
        print "Referencing/calling a variable or function outside this class. E.g. Some global variable/function."
2
Tushar Vazirani 1 Дек 2017 в 10:38

Позвольте мне сначала рассказать о сходстве метода, украшенного @classmethod vs @staticmethod.

Сходство . Их обоих можно вызывать для самого класса , а не только для экземпляра класса. Итак, оба они в некотором смысле являются методами класса .

Разница . Метод класса получит сам класс в качестве первого аргумента, а метод статики - нет.

Таким образом, статический метод, в некотором смысле, не связан с самим классом и просто висит там только потому, что он может иметь связанную функциональность.

>>> class Klaus:
        @classmethod
        def classmthd(*args):
            return args

        @staticmethod
        def staticmthd(*args):
            return args

# 1. Call classmethod without any arg
>>> Klaus.classmthd()  
(__main__.Klaus,)  # the class gets passed as the first argument

# 2. Call classmethod with 1 arg
>>> Klaus.classmthd('chumma')
(__main__.Klaus, 'chumma')

# 3. Call staticmethod without any arg
>>> Klaus.staticmthd()  
()

# 4. Call staticmethod with 1 arg
>>> Klaus.staticmthd('chumma')
('chumma',)
15
Pang 8 Ноя 2018 в 03:36

staticmethod - это метод, который ничего не знает о классе или экземпляре, для которого он был вызван. Он просто получает переданные аргументы, без первого неявного аргумента. Это в основном бесполезно в Python - вы можете просто использовать функцию модуля вместо статического метода.

classmethod , с другой стороны, это метод, который получает класс, к которому он был вызван, или класс экземпляра, к которому он был вызван, в качестве первого аргумента. Это полезно, когда вы хотите, чтобы метод был фабрикой для класса: поскольку он получает фактический класс, для которого он был вызван, в качестве первого аргумента, вы всегда можете создать экземпляр нужного класса, даже если задействованы подклассы. Посмотрите, например, как dict.fromkeys(), метод класса, возвращает экземпляр подкласса при вызове в подклассе:

>>> class DictSubclass(dict):
...     def __repr__(self):
...         return "DictSubclass"
... 
>>> dict.fromkeys("abc")
{'a': None, 'c': None, 'b': None}
>>> DictSubclass.fromkeys("abc")
DictSubclass
>>> 
784
Brian Burns 27 Май 2018 в 13:00

Здесь есть небольшая статья по этому вопросу

Функция @staticmethod - это не что иное, как функция, определенная внутри класса. Он вызывается без создания экземпляра класса первым. Это определение является неизменным через наследование.

Функция @classmethod также может вызываться без создания экземпляра класса, но ее определение следует через Sub class, а не Parent, посредством наследования. Это потому, что первым аргументом для функции @classmethod всегда должен быть cls (class).

73
Tom Neyland 3 Ноя 2009 в 19:02

Я начал изучать язык программирования на C ++, а затем на Java, а затем на Python, поэтому этот вопрос меня тоже очень беспокоил, пока я не понял простое использование каждого из них.

Метод класса: Python, в отличие от Java и C ++, не перегружен конструкторами. И поэтому для достижения этого вы можете использовать classmethod. Следующий пример объяснит это

Давайте рассмотрим, что у нас есть класс Person, который принимает два аргумента first_name и last_name и создает экземпляр Person.

class Person(object):

    def __init__(self, first_name, last_name):
        self.first_name = first_name
        self.last_name = last_name

Теперь, если требование возникает там, где вам нужно создать класс, используя только одно имя, просто first_name, вы не можете сделать что-то подобное в Python.

Это даст вам ошибку, когда вы попытаетесь создать объект (экземпляр).

class Person(object):

    def __init__(self, first_name, last_name):
        self.first_name = first_name
        self.last_name = last_name

    def __init__(self, first_name):
        self.first_name = first_name

Тем не менее, вы можете достичь того же, используя @classmethod, как указано ниже

class Person(object):

    def __init__(self, first_name, last_name):
        self.first_name = first_name
        self.last_name = last_name

    @classmethod
    def get_person(cls, first_name):
        return cls(first_name, "")

Статический метод: Это довольно просто, он не привязан к экземпляру или классу, и вы можете просто вызвать его, используя имя класса.

Итак, скажем, в приведенном выше примере вам нужна проверка, что first_name не должен превышать 20 символов, вы можете просто сделать это.

@staticmethod  
def validate_name(name):
    return len(name) <= 20

И вы можете просто позвонить, используя class name

Person.validate_name("Gaurang Shah")
41
sasurai 16 Апр 2019 в 14:21

@decorators были добавлены в python 2.4. Если вы используете python <2.4, вы можете использовать функции classmethod () и staticmethod ().

Например, если вы хотите создать фабричный метод (функция, возвращающая экземпляр другой реализации класса в зависимости от того, какой аргумент он получает), вы можете сделать что-то вроде:

class Cluster(object):

    def _is_cluster_for(cls, name):
        """
        see if this class is the cluster with this name
        this is a classmethod
        """ 
        return cls.__name__ == name
    _is_cluster_for = classmethod(_is_cluster_for)

    #static method
    def getCluster(name):
        """
        static factory method, should be in Cluster class
        returns a cluster object for the given name
        """
        for cls in Cluster.__subclasses__():
            if cls._is_cluster_for(name):
                return cls()
    getCluster = staticmethod(getCluster)

Также обратите внимание, что это хороший пример использования метода класса и статического метода. Статический метод явно принадлежит классу, поскольку он использует класс Cluster внутри. Метод класса нуждается только в информации о классе, а не в экземпляре объекта.

Еще одно преимущество превращения метода _is_cluster_for в метод класса - это то, что подкласс может решить изменить свою реализацию, возможно, потому что он довольно универсален и может обрабатывать более одного типа кластера, так что простая проверка имени класса не будет быть достаточным.

30
Jens Timmerman 20 Фев 2017 в 15:34

В чем разница между @staticmethod и @classmethod в Python?

Возможно, вы видели такой код Python, как этот псевдокод, который демонстрирует сигнатуры различных типов методов и предоставляет строку документации для объяснения каждого из них:

class Foo(object):

    def a_normal_instance_method(self, arg_1, kwarg_2=None):
        '''
        Return a value that is a function of the instance with its
        attributes, and other arguments such as arg_1 and kwarg2
        '''

    @staticmethod
    def a_static_method(arg_0):
        '''
        Return a value that is a function of arg_0. It does not know the 
        instance or class it is called from.
        '''

    @classmethod
    def a_class_method(cls, arg1):
        '''
        Return a value that is a function of the class and other arguments.
        respects subclassing, it is called with the class it is called from.
        '''

Нормальный метод экземпляра

Сначала я объясню a_normal_instance_method. Это точно называется « метод экземпляра ». Когда используется метод экземпляра, он используется как частичная функция (в отличие от функции total, определенной для всех значений при просмотре в исходном коде), то есть при использовании первый из аргументов предопределен как экземпляр объект со всеми заданными атрибутами. Он имеет экземпляр объекта, связанный с ним, и его необходимо вызывать из экземпляра объекта. Как правило, он будет обращаться к различным атрибутам экземпляра.

Например, это экземпляр строки:

', '

Если мы используем метод экземпляра join в этой строке, чтобы присоединиться к другой итерации, вполне очевидно, что это функция экземпляра, в дополнение к функции итеративного списка, ['a', 'b', 'c']:

>>> ', '.join(['a', 'b', 'c'])
'a, b, c'

Связанные методы

Методы экземпляра могут быть связаны через точечный поиск для последующего использования.

Например, это связывает метод str.join с экземпляром ':':

>>> join_with_colons = ':'.join 

И позже мы можем использовать это как функцию, с которой уже связан первый аргумент. Таким образом, он работает как частичная функция в экземпляре:

>>> join_with_colons('abcde')
'a:b:c:d:e'
>>> join_with_colons(['FF', 'FF', 'FF', 'FF', 'FF', 'FF'])
'FF:FF:FF:FF:FF:FF'

Статический метод

Статический метод not принимает экземпляр в качестве аргумента.

Это очень похоже на функцию уровня модуля.

Однако функция уровня модуля должна находиться в модуле и специально импортироваться в другие места, где она используется.

Однако, если он присоединен к объекту, он будет удобно следовать за объектом через импорт и наследование.

Пример статического метода - str.maketrans, перемещенный из модуля string в Python 3. Он делает таблицу перевода пригодной для использования str.translate. Это выглядит довольно глупо, когда используется из экземпляра строки, как показано ниже, но импорт функции из модуля string довольно неуклюж, и приятно иметь возможность вызывать ее из класса, как в str.maketrans

# demonstrate same function whether called from instance or not:
>>> ', '.maketrans('ABC', 'abc')
{65: 97, 66: 98, 67: 99}
>>> str.maketrans('ABC', 'abc')
{65: 97, 66: 98, 67: 99}

В Python 2 вы должны импортировать эту функцию из все менее полезного строкового модуля:

>>> import string
>>> 'ABCDEFG'.translate(string.maketrans('ABC', 'abc'))
'abcDEFG'

Метод класса

Метод класса похож на метод экземпляра в том, что он принимает неявный первый аргумент, но вместо того, чтобы брать экземпляр, он принимает класс. Часто они используются в качестве альтернативных конструкторов для лучшего семантического использования, и это будет поддерживать наследование.

Наиболее каноническим примером встроенного метода класса является dict.fromkeys. Он используется в качестве альтернативного конструктора dict (хорошо подходит для случаев, когда вы знаете, какие у вас ключи, и хотите для них значение по умолчанию.)

>>> dict.fromkeys(['a', 'b', 'c'])
{'c': None, 'b': None, 'a': None}

Когда мы создаем подкласс dict, мы можем использовать тот же конструктор, который создает экземпляр подкласса.

>>> class MyDict(dict): 'A dict subclass, use to demo classmethods'
>>> md = MyDict.fromkeys(['a', 'b', 'c'])
>>> md
{'a': None, 'c': None, 'b': None}
>>> type(md)
<class '__main__.MyDict'>

См. исходный код pandas для других подобных примеров альтернативных конструкторы, а также ознакомьтесь с официальной документацией Python по classmethod и < a href = "https://docs.python.org/library/functions.html#staticmethod" rel = "noreferrer"> staticmethod .

49
Aaron Hall 12 Июл 2017 в 15:47

Проанализируйте @staticmethod буквально , предоставив различные идеи.

Обычный метод класса - это неявный динамический метод, который принимает экземпляр в качестве первого аргумента.
Напротив, статический метод не принимает экземпляр в качестве первого аргумента, поэтому он называется «статическим» .

Статический метод - действительно такая нормальная функция, как и вне определения класса.
К счастью, он сгруппирован в класс только для того, чтобы стоять ближе там, где он применяется, или вы можете прокрутить круг, чтобы найти его.

1
Calculus 12 Дек 2017 в 11:18