Я упростил решение Реми Ф с помощью функций set_x/y/zlim
.
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import cm
import matplotlib.pyplot as plt
import numpy as np
fig = plt.figure()
ax = fig.gca(projection='3d')
ax.set_aspect('equal')
X = np.random.rand(100)*10+5
Y = np.random.rand(100)*5+2.5
Z = np.random.rand(100)*50+25
scat = ax.scatter(X, Y, Z)
max_range = np.array([X.max()-X.min(), Y.max()-Y.min(), Z.max()-Z.min()]).max() / 2.0
mid_x = (X.max()+X.min()) * 0.5
mid_y = (Y.max()+Y.min()) * 0.5
mid_z = (Z.max()+Z.min()) * 0.5
ax.set_xlim(mid_x - max_range, mid_x + max_range)
ax.set_ylim(mid_y - max_range, mid_y + max_range)
ax.set_zlim(mid_z - max_range, mid_z + max_range)
plt.show()
[/g1]
Может быть, вам поможет небольшой пример кода: обратите внимание на разницу в сигнатурах вызовов 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)
С помощью classmethods класс экземпляра объекта неявно передается как первый аргумент вместо 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)
Одно из применений, которое люди нашли для методов класса, - это создание наследуемых альтернативных конструкторов .
В staticmethods ни 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
, а скорее к классу
привязан к class_foo
.
print(a.class_foo)
# <bound method type.class_foo of <class '__main__.A'>>
Здесь статическим методом, даже если это метод, a.static_foo
просто возвращает
хорошая старая функция без привязки аргументов. 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>
staticmethod является методом, который ничего не знает о классе или экземпляре, к этому обратились. Это просто получает аргументы, которые были переданы, никакой неявный первый аргумент. Это в основном бесполезно в Python - можно просто использовать функцию модуля вместо staticmethod.
А classmethod, с другой стороны, является методом, который передается класс, к этому обратились, или класс экземпляра, к этому обратились как первый аргумент. Это полезно, когда Вы хотите, чтобы метод был фабрикой для класса: так как это получает фактический класс, к этому обратились как первый аргумент, можно всегда инстанцировать правильного класса, даже когда подклассы включены. Наблюдайте, например, как dict.fromkeys()
, classmethod, возвращает экземпляр подкласса, когда обращено подкласс:
>>> class DictSubclass(dict):
... def __repr__(self):
... return "DictSubclass"
...
>>> dict.fromkeys("abc")
{'a': None, 'c': None, 'b': None}
>>> DictSubclass.fromkeys("abc")
DictSubclass
>>>
В основном @classmethod
делает метод, первым аргументом которого является класс, которым это называют от (а не экземпляр класса), @staticmethod
не имеет никаких неявных аргументов.
@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'>
Я думаю, давая просто, версия 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
Метод класса получает класс как неявный первый аргумент, точно так же, как метод экземпляра получает экземпляр. Это - метод, который связывается с классом а не объектом класса. Это имеет доступ к состоянию класса, поскольку это берет параметр класса, который указывает на класс а не экземпляр объекта. Это может изменить состояние класса, которое применялось бы через все экземпляры класса. Например, это может изменить переменную класса, которая будет применима ко всем экземплярам.
, С другой стороны, статический метод не получает неявный первый аргумент, по сравнению с методами класса или методами экземпляра. И доступ can’t или изменяет состояние класса. Это только принадлежит классу, потому что с точки зрения дизайна, которая является корректным путем. Но с точки зрения функциональности не связывается, во времени выполнения, к классу.
как инструкция, используйте статические методы в качестве утилит, используйте методы класса, например, в качестве фабрики. Или возможно определить одиночный элемент. И используйте методы экземпляра смоделировать состояние и поведение экземпляров.
Надежда я был ясен!
Официальная документация python:
Метод класса получает класс как неявный первый аргумент, как и метод экземпляра получает экземпляр. Чтобы объявить метод класса, используйте это идиома:
класс C: @classmethod def f (cls, arg1, arg2, ...): ...
Форма
@classmethod
- это функция декоратор - см. Описание определения функций в Функция определения для деталей.Его можно вызвать либо на классе (например,
Cf ()
) или в экземпляре (например,C (). f ()
). Экземпляр игнорируется, за исключением своего класса. Если метод класса вызывается для производного class, объект производного класса передается как подразумеваемый первый аргумент.Методы класса отличаются от методов C ++ или статические методы Java. Если ты хочешь те, см.
staticmethod ()
в этом section.
Статический метод не получает неявный первый аргумент. Объявить статический метод, используйте эту идиому:
класс C: @staticmethod def f (arg1, arg2, ...): ...
Форма
@staticmethod
- это функция декоратор - см. Описание определения функций в Функция определения для деталей.Его можно вызвать либо на классе (например,
Cf ()
) или в экземпляре (например,C (). f ()
). Экземпляр игнорируется, за исключением своего класса.Статические методы в Python аналогичны к тем, что есть в Java или C ++. Для более продвинутая концепция, см.
classmethod ()
в этом разделе.
Здесь - короткая статья по этому вопросу.
Функция @staticmethod - это не что иное, как функция, определенная внутри класса. Он вызывается без предварительного создания экземпляра класса. Его определение неизменяемо через наследование.
Функция @classmethod также вызывается без создания экземпляра класса, но ее определение следует за подклассом, а не за родительским классом, через наследование. Это потому, что первым аргументом для функции @classmethod всегда должен быть cls (class).