В Python, могу ли я вызвать статический метод, используя self? [Дубликат]

Это очень интересная ошибка. (По-моему, это все равно ошибка) Ницца найти!

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


В спецификации CSS Я нашел:

'padding' Процент: относится к ширине содержащего блока

... что странно, но все в порядке.

Итак, с родителем width: 210px и дочерним padding-top: 50%, я получаю вычисленное / вычисленное значение padding-top: 96.5px - которое не является ожидаемым 105px.

Это связано с тем, что в Windows (я не уверен в других ОС) размер общих полос прокрутки по умолчанию 17px × 100% (или 100% × 17px для горизонтальных баров). Те 17px вычитаются до , вычисляя 50%, следовательно 50% of 193px = 96.5px.

1407
задан BartoszKP 5 June 2014 в 21:12
поделиться

8 ответов

Да, используя декодер staticmethod

class MyClass(object):
    @staticmethod
    def the_static_method(x):
        print x

MyClass.the_static_method(2) # outputs 2

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

class MyClass(object):
    def the_static_method(x):
        print x
    the_static_method = staticmethod(the_static_method)

MyClass.the_static_method(2) # outputs 2

. Это полностью идентично первому примеру (используя @staticmethod), просто не используя приятный декоратор синтаксис

Наконец, используйте staticmethod() экономно! Очень мало ситуаций, когда в Python необходимы статические методы, и я видел их много раз, когда отдельная функция «верхнего уровня» была бы более ясной.


Ниже приводится дословно из документации: :

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

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

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

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

Статические методы в Python аналогичны тем, которые были найдены в Java или C ++. Более подробную концепцию см. В classmethod() .

Дополнительные сведения о статических методах см. В документации по иерархии стандартного типа в . Иерархия стандартного типа .

Новое в версии 2.2.

Изменено в версии 2.4: Добавлен синтаксис конструктора функций.

1707
ответ дан jesterjunk 3 September 2018 в 15:22
поделиться

Статические методы в Python?

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

ClassName.StaticMethod()

Да, статические методы могут быть созданы таким образом (хотя немного больше Pythonic используют символы подчеркивания вместо методов CamelCase для методов):

class ClassName(object):

    @staticmethod
    def static_method(kwarg1=None):
        '''return a value that is a function of kwarg1'''

Вышеупомянутое использует синтаксис декоратора. Этот синтаксис эквивалентен

class ClassName(object):

    def static_method(kwarg1=None):
        '''return a value that is a function of kwarg1'''

    static_method = staticmethod(static_method)

. Его можно использовать так же, как вы описали:

ClassName.static_method()

Встроенный пример статического метода str.maketrans() в Python 3, который была функцией в модуле string в Python 2.


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

class ClassName(object):

    @classmethod
    def class_method(cls, kwarg1=None):
        '''return a value that is a function of the class and kwarg1'''

Обратите внимание, что cls не является обязательным именем для первого аргумента, но большинство опытных кодировщиков Python это плохо сделано, если вы используете что-либо еще.

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

new_instance = ClassName.class_method()

Встроенный пример: dict.fromkeys():

new_dict = dict.fromkeys(['key1', 'key2'])
28
ответ дан Aaron Hall 3 September 2018 в 15:22
поделиться

Вам действительно не нужно использовать декоратор @staticmethod. Просто объявляя метод (который не ожидает параметра self) и вызывает его из класса. Декоратор существует только там, где вы хотите иметь возможность вызвать его из экземпляра (что не было тем, что вы хотели сделать)

В основном вы просто используете функции, хотя ...

43
ответ дан hichris123 3 September 2018 в 15:22
поделиться

Помимо особенностей того, как ведут себя объекты статического метода , есть определенная красота, с которой вы можете столкнуться с ними, когда дело доходит до организации кода на уровне модуля.

# garden.py
def trim(a):
    pass

def strip(a):
    pass

def bunch(a, b):
    pass

def _foo(foo):
    pass

class powertools(object):
    """
    Provides much regarded gardening power tools.
    """
    @staticmethod
    def answer_to_the_ultimate_question_of_life_the_universe_and_everything():
        return 42

    @staticmethod
    def random():
        return 13

    @staticmethod
    def promise():
        return True

def _bar(baz, quux):
    pass

class _Dice(object):
    pass

class _6d(_Dice):
    pass

class _12d(_Dice):
    pass

class _Smarter:
    pass

class _MagicalPonies:
    pass

class _Samurai:
    pass

class Foo(_6d, _Samurai):
    pass

class Bar(_12d, _Smarter, _MagicalPonies):
    pass

...

# tests.py
import unittest
import garden

class GardenTests(unittest.TestCase):
    pass

class PowertoolsTests(unittest.TestCase):
    pass

class FooTests(unittest.TestCase):
    pass

class BarTests(unittest.TestCase):
    pass

...

# interactive.py
from garden import trim, bunch, Foo

f = trim(Foo())
bunch(f, Foo())

...

# my_garden.py
import garden
from garden import powertools

class _Cowboy(garden._Samurai):
    def hit():
        return powertools.promise() and powertools.random() or 0

class Foo(_Cowboy, garden.Foo):
    pass

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

Я часто считаю целесообразным применить этот подход к организации кода утилиты проекта. Довольно часто люди сразу бросаются и создают пакет utils и в итоге получают 9 модулей, из которых 120 LOC, а остальные - два десятка LOC в лучшем случае. Я предпочитаю начать с этого и преобразовать его в пакет и создать модули только для тех зверей, которые их действительно заслуживают:

# utils.py
class socket(object):
    @staticmethod
    def check_if_port_available(port):
        pass

    @staticmethod
    def get_free_port(port)
        pass

class image(object):
    @staticmethod
    def to_rgb(image):
        pass

    @staticmethod
    def to_cmyk(image):
        pass
9
ответ дан JJD 3 September 2018 в 15:22
поделиться

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

class Dog(object):
    def __init__(self, name):
        self.name = name

    def bark(self):
        if self.name == "Doggy":
            return barking_sound()
        else:
            return "yip yip"

def barking_sound():
    return "woof woof"

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

Предположим, что этот файл называется dogs.py. Чтобы использовать их, вы должны называть dogs.barking_sound() вместо dogs.Dog.barking_sound.

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

9
ответ дан Matt Woelk 3 September 2018 в 15:22
поделиться

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

(Обратите внимание, что этот ответ относится к Python 3.x. В Python 2.x вы получите TypeError для вызова метода для самого класса.)

Например:

class Dog:
    count = 0 # this is a class variable
    dogs = [] # this is a class variable

    def __init__(self, name):
        self.name = name #self.name is an instance variable
        Dog.count += 1
        Dog.dogs.append(name)

    def bark(self, n): # this is an instance method
        print("{} says: {}".format(self.name, "woof! " * n))

    def rollCall(n): #this is implicitly a class method (see comments below)
        print("There are {} dogs.".format(Dog.count))
        if n >= len(Dog.dogs) or n < 0:
            print("They are:")
            for dog in Dog.dogs:
                print("  {}".format(dog))
        else:
            print("The dog indexed at {} is {}.".format(n, Dog.dogs[n]))

fido = Dog("Fido")
fido.bark(3)
Dog.rollCall(-1)
rex = Dog("Rex")
Dog.rollCall(0)

В этом коде метод «rollCall» предполагает, что первый аргумент не является экземпляром (как если бы он был вызван экземпляром вместо класса). Пока «rollCall» вызывается из класса, а не экземпляра, код будет работать нормально. Если мы попытаемся вызвать «rollCall» из экземпляра, например:

rex.rollCall(-1)

, это приведет к возникновению исключения, потому что он отправит два аргумента: сам и -1 и «rollCall», определяется только для принятия одного аргумента.

Кстати, rex.rollCall () отправляет правильное количество аргументов, но также вызывает возбуждение исключения, поскольку теперь n будет представлять экземпляр Dog (т. е. , rex), когда функция ожидает, что число n будет численным.

Здесь происходит декорация: если мы предшествуем методу «rollCall» с

@staticmethod

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

rex.rollCall(-1)

будет работать. Вставка @staticmethod перед определением метода затем останавливает экземпляр от отправки себя в качестве аргумента.

Вы можете проверить это, попробовав следующий код с и без строки @staticmethod, прокомментированной.

class Dog:
    count = 0 # this is a class variable
    dogs = [] # this is a class variable

    def __init__(self, name):
        self.name = name #self.name is an instance variable
        Dog.count += 1
        Dog.dogs.append(name)

    def bark(self, n): # this is an instance method
        print("{} says: {}".format(self.name, "woof! " * n))

    @staticmethod
    def rollCall(n):
        print("There are {} dogs.".format(Dog.count))
        if n >= len(Dog.dogs) or n < 0:
            print("They are:")
            for dog in Dog.dogs:
                print("  {}".format(dog))
        else:
            print("The dog indexed at {} is {}.".format(n, Dog.dogs[n]))


fido = Dog("Fido")
fido.bark(3)
Dog.rollCall(-1)
rex = Dog("Rex")
Dog.rollCall(0)
rex.rollCall(-1)
178
ответ дан Md. Abu Nafee Ibna Zahid 3 September 2018 в 15:22
поделиться

Время от времени я сталкиваюсь с этим вопросом. Пример использования и пример, который мне нравится, это:

jeffs@jeffs-desktop:/home/jeffs  $ python36
Python 3.6.1 (default, Sep  7 2017, 16:36:03) 
[GCC 6.3.0 20170406] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import cmath
>>> print(cmath.sqrt(-4))
2j
>>>
>>> dir(cmath)
['__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'acos', 'acosh', 'asin', 'asinh', 'atan', 'atanh', 'cos', 'cosh', 'e', 'exp', 'inf', 'infj', 'isclose', 'isfinite', 'isinf', 'isnan', 'log', 'log10', 'nan', 'nanj', 'phase', 'pi', 'polar', 'rect', 'sin', 'sinh', 'sqrt', 'tan', 'tanh', 'tau']
>>> 

Не имеет смысла создавать объект класса cmath, потому что в CMAT-объекте нет состояния. Однако cmath - это совокупность методов, которые в какой-то мере связаны. В моем примере выше все функции в cmath в некотором роде действуют на сложные числа.

-1
ответ дан Moritz 3 September 2018 в 15:22
поделиться

Да, проверьте декоратор staticmethod :

>>> class C:
...     @staticmethod
...     def hello():
...             print "Hello World"
...
>>> C.hello()
Hello World
74
ответ дан Paolo Bergantino 3 September 2018 в 15:22
поделиться
Другие вопросы по тегам:

Похожие вопросы: