Это очень интересная ошибка. (По-моему, это все равно ошибка) Ницца найти!
Что касается , как , чтобы установить его, я бы рекомендовал ответ Камило Мартина. Но что касается , почему , я хотел бы объяснить это немного, если вы, ребята, не возражаете.
В спецификации CSS Я нашел:
'padding' Процент: относится к ширине содержащего блока
... что странно, но все в порядке.
Итак, с родителем
width: 210px
и дочернимpadding-top: 50%
, я получаю вычисленное / вычисленное значениеpadding-top: 96.5px
- которое не является ожидаемым105px
.Это связано с тем, что в Windows (я не уверен в других ОС) размер общих полос прокрутки по умолчанию
17px × 100%
(или100% × 17px
для горизонтальных баров). Те17px
вычитаются до , вычисляя50%
, следовательно50% of 193px = 96.5px
.
Да, используя декодер 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: Добавлен синтаксис конструктора функций.
blockquote>
Статические методы в Python?
Возможно ли иметь статические методы в Python, чтобы я мог их вызывать без инициализации класса, например:
blockquote>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'])
Вам действительно не нужно использовать декоратор @staticmethod
. Просто объявляя метод (который не ожидает параметра self) и вызывает его из класса. Декоратор существует только там, где вы хотите иметь возможность вызвать его из экземпляра (что не было тем, что вы хотели сделать)
В основном вы просто используете функции, хотя ...
Помимо особенностей того, как ведут себя объекты статического метода , есть определенная красота, с которой вы можете столкнуться с ними, когда дело доходит до организации кода на уровне модуля.
# 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
Возможно, самым простым вариантом является просто поместить эти функции вне класса:
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 декоратора.
Я думаю, что Стивен на самом деле прав . Чтобы ответить на исходный вопрос, затем, чтобы настроить метод класса, просто предположим, что первый аргумент не будет вызывающим экземпляром, а затем убедитесь, что вы вызываете метод только из класса.
(Обратите внимание, что этот ответ относится к 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)
Время от времени я сталкиваюсь с этим вопросом. Пример использования и пример, который мне нравится, это:
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 в некотором роде действуют на сложные числа.
Да, проверьте декоратор staticmethod :
>>> class C:
... @staticmethod
... def hello():
... print "Hello World"
...
>>> C.hello()
Hello World