@staticmethod와 @classmethod의 차이점
로 장식된 기능과 로 장식된 기능의 차이점은 무엇입니까?
「」의 해 주세요.★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★foo,class_foo ★★★★★★★★★★★★★★★★★」static_foo:
class A(object):
def foo(self, x):
print(f"executing foo({self}, {x})")
@classmethod
def class_foo(cls, x):
print(f"executing class_foo({cls}, {x})")
@staticmethod
def static_foo(x):
print(f"executing static_foo({x})")
a = A()
오브젝트 인스턴스가 메서드를 호출하는 일반적인 방법은 다음과 같습니다. 인스턴스 「」는,a는 암묵적으로 첫 번째 인수로 전달됩니다.
a.foo(1)
# executing foo(<__main__.A object at 0xb7dbef0c>, 1)
class 메서드에서는 오브젝트인스턴스의 클래스가 암묵적으로 첫 번째 인수로 전달됩니다.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수 있는 것이 인스턴스(instance)를 의 " 수 .a함수의 첫 번째 인수로 바인드됩니다. fooa.foo1번으로 하다
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'올레'를 사용하다 static_foo 인수가 1개입니다.a.static_foo1번으로 하다
print(a.static_foo)
# <function static_foo at 0xb7d479cc>
물론 이 전화할 일이 .static_foo학급과 함께A★★★★★★ 。
print(A.static_foo)
# <function static_foo at 0xb7d479cc>
static 메서드는 호출된 클래스 또는 인스턴스에 대해 아무것도 모르는 메서드입니다.전달된 인수만 얻을 뿐 암묵적인 첫 번째 인수는 얻을 수 없습니다.Python에서는 기본적으로 쓸모가 없습니다.정적인 방법 대신 모듈 함수를 사용할 수 있습니다.
반면 클래스 메서드는 첫 번째 인수로 호출된 클래스 또는 호출된 인스턴스의 클래스를 전달하는 메서드입니다.이것은 메서드를 클래스의 팩토리로 하는 경우에 편리합니다.첫 번째 인수로 호출된 실제 클래스를 취득하기 때문에 서브클래스가 관련되어 있는 경우에도 항상 올바른 클래스를 인스턴스화할 수 있습니다.예를 들어 어떻게 하는지 관찰한다.dict.fromkeys()method 는 서브클래스 class 메서드로 되었을 때 를 반환합니다.
>>> class DictSubclass(dict):
... def __repr__(self):
... return "DictSubclass"
...
>>> dict.fromkeys("abc")
{'a': None, 'c': None, 'b': None}
>>> DictSubclass.fromkeys("abc")
DictSubclass
>>>
으로는 ★★★★★★★★★★★★★★.@classmethod첫 번째 인스턴스가 .@staticmethod에는 암묵적인 인수가 없습니다.
공식 Python 문서:
인스턴스 메서드가 인스턴스를 수신하는 것과 마찬가지로 클래스 메서드는 클래스를 암묵적인 첫 번째 인수로 수신합니다.클래스 메서드를 선언하려면 다음 관용구를 사용합니다.
class C: @classmethod def f(cls, arg1, arg2, ...): ...
@classmethod폼은 함수 데코레이터입니다.자세한 내용은 함수 정의의 함수 정의에 대한 설명을 참조하십시오.에서 호출할 수 클래스에서는 할 수 있습니다).
C.f()등에C().f()클래스를 제외하고 인스턴스는 무시됩니다.파생 클래스에 대해 클래스 메서드가 호출되면 파생 클래스 개체가 암시된 첫 번째 인수로 전달됩니다.클래스 메서드는 C++ 또는 Java 정적 메서드와 다릅니다.필요한 경우는, 이 항을 참조해 주세요.
스태틱 메서드는 암묵적인 첫 번째 인수를 수신하지 않습니다.스태틱 방식을 선언하려면 다음 관용구를 사용합니다.
class C: @staticmethod def f(arg1, arg2, ...): ...
@staticmethod폼은 함수 데코레이터입니다.자세한 내용은 함수 정의의 함수 정의에 대한 설명을 참조하십시오.에서 호출할 수 클래스에서는 할 수 있습니다).
C.f()등에C().f()클래스를 제외하고 인스턴스는 무시됩니다.Python의 정적 메서드는 Java 또는 C++와 유사합니다.보다 고도의 개념에 대해서는, 이 항을 참조해 주세요.
@static method 또는 @class method 중 어느 쪽을 사용할지 결정하려면 메서드 내부를 확인해야 합니다.메서드가 클래스의 다른 변수/메서드에 액세스할 경우 @classmethod를 사용합니다.한편, 사용하시는 메서드가 클래스의 다른 부분에 영향을 주지 않는 경우는, @static method 를 사용합니다.
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 another class,
# you don't have to rename the referenced class
@classmethod
def make_apple_juice(cls, number_of_apples):
print('Making juice:')
for i in range(number_of_apples):
cls._juice_this(i)
@classmethod
def _juice_this(cls, apple):
print('Juicing apple %d...' % apple)
cls._counter += 1
여기 이 질문에 대한 짧은 기사가 있습니다.
@staticmethod 함수는 클래스 내에서 정의된 함수에 지나지 않습니다.먼저 클래스를 인스턴스화하지 않고 호출할 수 있습니다.그 정의는 상속을 통해 불변합니다.
@classmethod 함수는 클래스를 인스턴스화하지 않고 호출할 수도 있지만 그 정의는 상속을 통해 부모 클래스가 아닌 서브 클래스를 따릅니다.그 이유는 @classmethod 함수의 첫 번째 인수는 항상 cls(class)여야 하기 때문입니다.
Python의 @staticmethod와 @classmethod의 차이점은 무엇입니까?
이 의사 코드와 같은 Python 코드는 다양한 메서드유형의 시그니처를 나타내고 각 메서드를 설명하는 docstring을 제공합니다.
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이를 정확히 '인스턴스 방식'이라고 합니다.인스턴스 메서드를 사용하면 (소스 코드로 표시할 때 모든 값에 대해 정의된 총 함수와 달리) 부분 함수로 사용됩니다.즉, 첫 번째 인수는 지정된 모든 Atribut과 함께 객체의 인스턴스로 정의됩니다.오브젝트의 인스턴스가 바인드되어 있기 때문에 오브젝트의 인스턴스에서 호출해야 합니다.일반적으로 인스턴스의 다양한 속성에 액세스합니다.
예를 들어, 이것은 문자열의 인스턴스입니다.
', '
메서드를 , ""는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'
정적 방법
static 메서드는 인스턴스를 인수로 받아들이지 않습니다.
모듈 레벨의 기능과 매우 유사합니다.
단, 모듈레벨 함수는 모듈에 존재해야 하며 사용하는 다른 곳으로 특별히 Import해야 합니다.
그러나 오브젝트에 첨부되어 있으면 Import 및 상속을 통해 오브젝트를 쉽게 추적할 수 있습니다.
스태틱 방식의 예는 다음과 같습니다.str.maketransstringPython 3 의 python 。번역테이블을사용하는데적합합니다.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해야 합니다.
>>> 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'>
대체 컨스트럭터의 다른 유사한 예에 대해서는 판다의 소스 코드를 참조해 주세요.및의 Python 공식 메뉴얼도 참조해 주세요.
저는 C++로 프로그래밍 언어를 배우기 시작했고, 그 다음에 Java와 Python으로 프로그래밍 언어를 배웠고, 그래서 이 질문도 제가 각각의 간단한 사용법을 이해할 때까지 저를 많이 괴롭혔습니다.
클래스 방법:자바나 C++와 달리 Python은 컨스트럭터 오버로드가 없습니다.이를 실현하기 위해서는classmethod 이하겠습니다.
그럼 이렇게 한 번 요?Person 의 인수를 " " " " " "first_name ★★★★★★★★★★★★★★★★★」last_name and스스 of of of이다의 를 만듭니다.Person
class Person(object):
def __init__(self, first_name, last_name):
self.first_name = first_name
self.last_name = last_name
하나의 , '클래스를 만듭니다'라고 하면 .first_namePython에서는 이런 일을 할 수 없습니다.
오브젝트(인스턴스)를 작성하려고 하면 오류가 발생합니다.
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_name20년 전을 사용하다
@staticmethod
def validate_name(name):
return len(name) <= 20
그냥 요.class name
Person.validate_name("Gaurang Shah")
첫 번째 인수만 다릅니다.
- normal 메서드: 현재 오브젝트는 자동으로 (수치) 첫 번째 인수로 전달됩니다.
- classmethod: 현재 객체의 클래스는 자동으로 (수치) fist 인수로 전달됩니다.
- static method: 추가 인수는 자동으로 전달되지 않습니다.함수에 전달한 내용이 바로 그 결과입니다.
좀 더 자세히...
통상법
모든 객체 지향 언어에서와 같이 "표준" 메서드입니다. 인수가 됩니다.self, 즉
def f(self, x, y)
2년 전 self자동으로 전달되며 객체 자체입니다.와 비슷합니다.this를 들어c++에으로 나타납니다.
실제로 첫 번째 인수는 호출할 필요가 없습니다.
self
클래스 방식
메서드가 장식되었을 때
@classmethod
def f(cls, x, y)
자동으로 제공된 인수는 self, 단, 의 클래스 self.
정적 방법
메서드가 장식되었을 때
@staticmethod
def f(x, y)
메서드에는 자동 인수가 전혀 부여되지 않습니다.호출된 파라미터만 지정됩니다.
사용법
classmethod대체 생성자에 주로 사용됩니다.staticmethod는 오브젝트 상태 또는 클래스 자체의 구조를 사용하지 않습니다.을 사용법명령어는 을 가진 함수 Java의 "Java"와 에.Math★★★★★★★★★★★★★★★★★★★★★★★」
class Point
def __init__(self, x, y):
self.x = x
self.y = y
@classmethod
def frompolar(cls, radius, angle):
"""The `cls` argument is the `Point` class itself"""
return cls(radius * cos(angle), radius * sin(angle))
@staticmethod
def angle(x, y):
"""this could be outside the class, but we put it here
just because we think it is logically related to the class."""
return atan(y, x)
p1 = Point(3, 2)
p2 = Point.frompolar(3, pi/4)
angle = Point.angle(3, 2)
'하시겠습니까?'가 더 합니다.@classmethod »@staticmethod
@classmethod즉 생성되는 객체의를 만들 수 .이는 싱글톤 또는 작성된 객체의 인스턴스 수를 제어하는 팩토리 클래스를 수행하는 데 유용한 방법입니다.
@staticmethod퍼포먼스 향상에 한계가 있지만 클래스 밖에서는 스탠드아론 함수로 달성할 수 없었던 정적 메서드를 클래스 내에서 생산적으로 사용할 수 있는 경우는 아직 없습니다.
정적 방법:
- 자기 인수가 없는 단순한 함수.
- 인스턴스 속성이 아닌 클래스 속성으로 작업합니다.
- 클래스와 인스턴스 모두에서 호출할 수 있습니다.
- 빌트인 함수의 static method()를 사용하여 작성합니다.
스태틱 방식의 이점:
- 클래스 스코프의 함수 이름을 현지화합니다.
- 기능 코드를 사용하는 곳으로 이동합니다.
각 메서드를 특별히 Import할 필요가 없기 때문에 모듈 수준의 함수보다 Import가 편리함
@staticmethod def some_static_method(*args, **kwds): pass
클래스 메서드:
- 첫 번째 인수를 클래스 이름으로 하는 함수.
- 클래스와 인스턴스 모두에서 호출할 수 있습니다.
classmethod 삽입 함수를 사용하여 생성됩니다.
@classmethod def some_class_method(cls, *args, **kwds): pass
@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)
또한 이것은 클래스 메서드와 스태틱메서드를 사용하는 경우의 좋은 예입니다.스태틱메서드는 내부에서 클러스터 클래스를 사용하기 때문에 클래스에 확실히 속합니다.class 메서드에서는 클래스에 대한 정보만 필요하며 개체의 인스턴스는 필요하지 않습니다.
또 다른 장점은_is_cluster_for할 수 있습니다.할 수 .아마도 매우 범용적이고 여러 유형의 클러스터를 처리할 수 있기 때문에 클래스 이름을 확인하는 것만으로는 충분하지 않습니다.
먼저 @classmethod와 @staticmethod의 유사점을 말씀드리겠습니다.
유사성:둘 다 클래스의 인스턴스가 아니라 클래스 자체에 호출할 수 있습니다.어떤 의미에서는 둘 다 Class의 메서드입니다.
차이점:클래스 메서드는 클래스 자체를 첫 번째 인수로 수신하지만 정적 메서드는 수신하지 않습니다.
따라서 정적 메서드는 어떤 의미에서 클래스 자체에 얽매이지 않고 단지 관련된 기능을 가지고 있을 수 있기 때문에 계속 사용할 수 있습니다.
>>> 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',)
@staticmethod는 첫번째 인수로서 콜 상태로 .classmethod는 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 함수는 클래스 내에서 정의된 함수에 지나지 않습니다.먼저 클래스를 인스턴스화하지 않고 호출할 수 있습니다.그 정의는 상속을 통해 불변합니다.
- Python은 오브젝트의 bound-method를 인스턴스화할 필요가 없습니다.
- 코드의 가독성을 용이하게 하고 오브젝트 자체의 상태에 의존하지 않습니다.
@classmethod 또한 클래스를 인스턴스화하지 않고 호출할 수 있지만, 그 정의는 하위 클래스를 따르며 상속을 통해 상위 클래스가 아닌 하위 클래스로 재정의할 수 있습니다.왜냐하면 첫 번째 주장은@classmethod함수는 항상 cls(클래스)여야 합니다.
- 일종의 전처리를 사용하여 클래스의 인스턴스를 만드는 데 사용되는 팩토리 메서드입니다.
- 정적 메서드를 호출하는 정적 메서드: 정적 메서드를 여러 정적 메서드로 분할하는 경우 클래스 이름을 하드 코드하지 말고 클래스 메서드를 사용해야 합니다.
static method vs class method에 관한 다른 고려사항은 상속입니다.다음과 같은 클래스가 있다고 가정합니다.
class Foo(object):
@staticmethod
def bar():
return "In Foo"
'하다'를 덮어쓰게 .bar()「이것들」은 다음과 같습니다.
class Foo2(Foo):
@staticmethod
def bar():
return "In Foo2"
하면 되는데, 되어 요.bar()(「」(「」))Foo2 그 의 것을 할 수 ).들어 '다보다'라고 하면요.Foo2 had had had had had had had had had had had had had had had had had 。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 사항, 그 것을 기억해야 bar()★★★★★★★★★★★★★★★★★★」
나에게 이것은 오픈/클로즈 원칙을 약간 위반하는 것이다.왜냐하면 이 결정은 오픈/클로즈 원칙에서 내려진 것이기 때문이다.Foo파생 클래스의 공통 코드를 리팩터링하는 기능에 영향을 줍니다(즉, 확장에 대한 개방성이 낮습니다). ifbar() wereclassmethod우린 괜찮을 거야
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
반()은 귀도 반 로섬(Python)을 지칭한 적이 있다.staticmethod님은 '사고'로 간주됩니다.https://mail.python.org/pipermail/python-ideas/2012-May/014969.html
정적 메서드가 얼마나 제한적인지 알고 있습니다.(기본적으로 사고입니다.Python 2.2일 전 새로운 스타일의 클래스와 디스크립터를 개발했을 때 클래스 메서드를 구현하려고 했는데 처음에는 이해하지 못하고 실수로 정적 메서드를 먼저 구현했습니다.그리고 나서 그것들을 제거하고 클래스 메서드만 제공하기에는 너무 늦었다.
기타 : https://mail.python.org/pipermail/python-ideas/2016-July/041189.html
솔직히 말하면 static 메서드는 뭔가 잘못된 것입니다.Java 클래스 메서드 같은 것을 하려고 했는데 막상 출시되자 정말 필요한 것은 클래스 메서드라는 것을 알게 되었습니다.하지만 정적 방법을 없애기에는 너무 늦었다.
예를 들어 기본적인 차이점을 설명하겠습니다.
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 메서드와 class 메서드를 직접 호출할 수 있습니다.
# A.run_self() # wrong
A.run_static()
A.run_class()
2-스태틱 메서드는 셀프 메서드를 호출할 수 없지만 다른 스태틱 메서드와 클래스 메서드를 호출할 수 있습니다.
3- 정적 메서드는 클래스에 속하며 개체를 전혀 사용하지 않습니다.
4- 클래스 메서드는 객체에 바인딩되지 않고 클래스에 바인딩됩니다.
이 차이는 상속이 있을 때 발생합니다.
부모 클래스와 자녀 클래스가 있다고 가정합니다.@static method를 사용하는 경우 print_name 메서드를 두 번 써야 합니다.이는 클래스 이름이 인쇄 행에 기록되어야 하기 때문입니다.
class Parent:
_class_name = "Parent"
@staticmethod
def print_name():
print(Parent._class_name)
class Child(Parent):
_class_name = "Child"
@staticmethod
def print_name():
print(Child._class_name)
Parent.print_name()
Child.print_name()
단, @classmethod의 경우 print_name 메서드를 두 번 쓸 필요는 없습니다.
class Parent:
_class_name = "Parent"
@classmethod
def print_name(cls):
print(cls._class_name)
class Child(Parent):
_class_name = "Child"
Parent.print_name()
Child.print_name()
Python에는 여러 개의 내장 장식기가 포함되어 있습니다.빅3는 다음과 같습니다.
@classmethod
@staticmethod
@property
먼저 이 클래스의 인스턴스(이 클래스를 초기화한 후)를 사용하여 클래스의 함수를 호출할 수 있습니다.
@classmethod는 클래스의 인스턴스로서뿐만 아니라 클래스 자체에 의해서도 함수를 첫 번째 인수로 직접 호출하는 방법입니다.
@staticmethod는 함수를 클래스에 넣는 방법(논리적으로 함수가 속해 있기 때문에)으로, 클래스에 액세스 할 필요가 없는 것을 나타냅니다(따라서 함수 정의에 사용할 필요가 없습니다).
다음 클래스에 대해 생각해 보겠습니다.
class DecoratorTest(object):
def __init__(self):
pass
def doubler(self, x):
return x*2
@classmethod
def class_doubler(cls, x): # we need to use 'cls' instead of 'self'; 'cls' reference to the class instead of an instance of the class
return x*2
@staticmethod
def static_doubler(x): # no need adding 'self' here; static_doubler() could be just a function not inside the class
return x*2
어떻게 동작하는지 봅시다.
decor = DecoratorTest()
print(decor.doubler(5))
# 10
print(decor.class_doubler(5)) # a call with an instance of a class
# 10
print(DecoratorTest.class_doubler(5)) # a direct call by the class itself
# 10
# staticmethod could be called in the same way as classmethod.
print(decor.static_doubler(5)) # as an instance of the class
# 10
print(DecoratorTest.static_doubler(5)) # or as a direct call
# 10
이러한 방법의 사용 사례를 몇 가지 볼 수 있습니다.
: 읽으면 됩니다.@property여기 장식가
인스턴스 방법:
+ 개체 인스턴스 상태를 수정할 수 있습니다.
+ 클래스 상태 수정 가능
클래스 방법:
- 개체 인스턴스 상태를 수정할 수 없습니다.
+ 클래스 상태 수정 가능
정적 방법:
- 개체 인스턴스 상태를 수정할 수 없습니다.
- 클래스 상태를 수정할 수 없습니다.
class MyClass:
'''
Instance method has a mandatory first attribute self which represent the instance itself.
Instance method must be called by a instantiated instance.
'''
def method(self):
return 'instance method called', self
'''
Class method has a mandatory first attribute cls which represent the class itself.
Class method can be called by an instance or by the class directly.
Its most common using scenario is to define a factory method.
'''
@classmethod
def class_method(cls):
return 'class method called', cls
'''
Static method doesn’t have any attributes of instances or the class.
It also can be called by an instance or by the class directly.
Its most common using scenario is to define some helper or utility functions which are closely relative to the class.
'''
@staticmethod
def static_method():
return 'static method called'
obj = MyClass()
print(obj.method())
print(obj.class_method()) # MyClass.class_method()
print(obj.static_method()) # MyClass.static_method()
출력:
('instance method called', <__main__.MyClass object at 0x100fb3940>)
('class method called', <class '__main__.MyClass'>)
static method called
실제로 오브젝트 인스턴스에 액세스할 수 있는 인스턴스 메서드입니다.즉, 클래스 메서드에서는 클래스 자체에 액세스할 수 있습니다.그러나 클래스 메서드는 기존 객체에 대해 별로 신경을 쓰지 않기 때문에 어떤 객체에도 해당되지 않습니다.단, 오브젝트인스턴스에서는 클래스 메서드와 스태틱메서드를 모두 호출할 수 있습니다.이 방법은 실제로 효과가 없기 때문에 여기서 정적 메서드를 호출하면 작동하며 어떤 메서드를 호출해야 하는지 알 수 있습니다.
일부 유틸리티 태스크에는 Static 메서드가 사용되고 공장 메서드에는 클래스 메서드가 사용됩니다.공장 메서드는 다양한 사용 사례에 대한 클래스 개체를 반환할 수 있습니다.
마지막으로 이해를 돕기 위한 간단한 예를 제시하겠습니다.
class Student:
def __init__(self, first_name, last_name):
self.first_name = first_name
self.last_name = last_name
@classmethod
def get_from_string(cls, name_string: str):
first_name, last_name = name_string.split()
if Student.validate_name(first_name) and Student.validate_name(last_name):
return cls(first_name, last_name)
else:
print('Invalid Names')
@staticmethod
def validate_name(name):
return len(name) <= 10
stackoverflow_student = Student.get_from_string('Name Surname')
print(stackoverflow_student.first_name) # Name
print(stackoverflow_student.last_name) # Surname
@classmethod : 여러 사용자에 의한 레코드 갱신 등 해당 클래스의 모든 인스턴스에 대한 공유 글로벌액세스를 작성할 수 있습니다.특히 싱글톤을 만들 때도 full을 사용한다는 것을 알았습니다.:)
@static method: 클래스 또는 인스턴스와 관련된 것은 없습니다.단, 가독성을 위해 정적 방법을 사용할 수 있습니다.
제 기고문은 두 사람 사이의 차이를 보여 줍니다.@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)
'''
"""
인스턴스 메서드가 인스턴스를 수신하는 것과 마찬가지로 클래스 메서드는 클래스를 암묵적인 첫 번째 인수로 수신합니다.이것은 클래스의 객체가 아닌 클래스에 바인딩된 메서드입니다.오브젝트 인스턴스가 아닌 클래스를 가리키는 클래스 파라미터를 취득하기 때문에 클래스 상태에 액세스 할 수 있습니다.클래스의 모든 인스턴스에 적용되는 클래스 상태를 수정할 수 있습니다.예를 들어 모든 인스턴스에 적용되는 클래스 변수를 수정할 수 있습니다.
반면 정적 메서드는 클래스 메서드 또는 인스턴스 메서드와 비교하여 암묵적인 첫 번째 인수를 수신하지 않습니다.또한 클래스 상태에 액세스하거나 수정할 수 없습니다.설계 관점에서 보면 이것이 올바른 방법이기 때문에 클래스에만 속합니다.그러나 기능 측면에서는 실행 시 클래스에 구속되지 않습니다.
가이드라인으로 정적 메서드를 유틸리티로 사용하거나 클래스 메서드를 factory로 사용하거나 싱글톤을 정의합니다.인스턴스 메서드를 사용하여 인스턴스의 상태와 동작을 모델링합니다.
내 말이 맞았길 바래!
다음과 같은 차이를 고려할 수 있습니다.
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데코레이터
다른 사건들은 utbus답변으로 잘 해결되었다.
클래스 메서드는 이름에서 알 수 있듯이 객체가 아닌 클래스를 변경하는 데 사용됩니다.클래스를 변경하려면 클래스 속성(오브젝트 속성이 아님)을 수정합니다.이렇게 하면 클래스를 갱신할 수 있습니다.이것이 클래스 메서드가 클래스(일반적으로 '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."
만의 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
@static method를 분석하면 말 그대로 다양한 통찰력을 얻을 수 있습니다.
클래스의 일반 메서드는 인스턴스를 첫 번째 인수로 사용하는 암묵적인 동적 메서드입니다.
반면 static 메서드는 인스턴스를 첫 번째 인수로 받아들이지 않으므로 'static'이라고 합니다.
스태틱 메서드는 클래스 정의 외부에 있는 것과 같은 정규 함수입니다.
적용된 위치에 더 가까이 서 있기 위해 클래스별로 그룹화되거나 스크롤하여 찾을 수 있습니다.
서브클래싱을 할 때 매우 중요한 실제적인 차이가 발생합니다.괜찮으시다면 @unutbu의 예를 들어 보겠습니다.
class A:
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)
class B(A):
pass
»class_foo이치노
A.class_foo(1)
# => executing class_foo(<class '__main__.A'>, 1)
B.class_foo(1)
# => executing class_foo(<class '__main__.B'>, 1)
»static_fooA ★★★★★★★★★★★★★★★★★」B:
A.static_foo(1)
# => executing static_foo(1)
B.static_foo(1)
# => executing static_foo(1)
해서 을 쓸것은 .staticmethod직접 클래스를 참조하기만 하면 됩니다.즉, 서브클래스의 스태틱메서드는 부모 클래스를 참조합니다.
class A:
@classmethod
def class_qux(cls, x):
print(f"executing class_qux({cls}, {x})")
@classmethod
def class_bar(cls, x):
cls.class_qux(x)
@staticmethod
def static_bar(x):
A.class_qux(x)
class B(A):
pass
A.class_bar(1)
# => executing class_qux(<class '__main__.A'>, 1)
B.class_bar(1)
# => executing class_qux(<class '__main__.B'>, 1)
A.static_bar(1)
# => executing class_qux(<class '__main__.A'>, 1)
B.static_bar(1)
# => executing class_qux(<class '__main__.A'>, 1)
tldr;
A staticmethod본질적으로 클래스(그리고 결과적으로 그 인스턴스)에 바인드된 함수입니다.
A classmethod 가능한 것입니다.staticmethod.
상세한 것에 대하여는, 다른 사람의 훌륭한 답변을 참조해 주세요.
먼저 두 가지 개념을 이해하는 데 사용할 코드 예를 들어 보겠습니다.
class Employee:
NO_OF_EMPLOYEES = 0
def __init__(self, first_name, last_name, salary):
self.first_name = first_name
self.last_name = last_name
self.salary = salary
self.increment_employees()
def give_raise(self, amount):
self.salary += amount
@classmethod
def employee_from_full_name(cls, full_name, salary):
split_name = full_name.split(' ')
first_name = split_name[0]
last_name = split_name[1]
return cls(first_name, last_name, salary)
@classmethod
def increment_employees(cls):
cls.NO_OF_EMPLOYEES += 1
@staticmethod
def get_employee_legal_obligations_txt():
legal_obligations = """
1. An employee must complete 8 hours per working day
2. ...
"""
return legal_obligations
클래스 방식
클래스 메서드는 클래스 자체를 암묵적인 인수로 받아들이고 옵션으로 정의에서 지정된 다른 모든 인수로 받아들입니다.클래스 메서드는 오브젝트인스턴스(instance 메서드 등)에 액세스 할 수 없다는 것을 이해하는 것이 중요합니다.따라서 클래스 메서드는 인스턴스화된 객체의 상태를 변경하는 데 사용할 수 없으며 대신 해당 클래스의 모든 인스턴스 간에 공유되는 클래스 상태를 변경할 수 있습니다.클래스 메서드는 일반적으로 클래스 자체에 액세스해야 할 때 유용합니다.예를 들어 팩토리 메서드를 만드는 경우 클래스의 인스턴스를 만드는 메서드입니다.즉, 클래스 메서드가 대체 생성자 역할을 할 수 있습니다.
코드에서는 ""의 입니다.Employee는 세 인수를 할 수 .first_name,last_name ★★★★★★★★★★★★★★★★★」salary.
employee_1 = Employee('Andrew', 'Brown', 85000)
print(employee_1.first_name)
print(employee_1.salary)
'Andrew'
85000
이제 이름과 성이 공백으로 구분된 단일 필드에 직원 이름을 입력할 수 있다고 가정합니다.인 이, 리, 리, 리, 리, method, method, method, method, method, method, method, method, method을 사용할 수 .employee_from_full_name3번입니다.할 때 이 합니다.이것은 메서드를 호출할 때 제공되지 않는 암묵적인 인수입니다.파이썬
employee_2 = Employee.employee_from_full_name('John Black', 95000)
print(employee_2.first_name)
print(employee_2.salary)
'John'
95000
, 전화는 「이렇게 하다」라고 하는 합니다.employee_from_full_name오브젝트 인스턴스의 경우, 이 상황에서는 의미가 없습니다.
employee_1 = Employee('Andrew', 'Brown', 85000)
employee_2 = employee_1.employee_from_full_name('John Black', 95000)
클래스 메서드를 만들고 싶은 또 다른 이유는 클래스 상태를 변경해야 할 때입니다.예에서는 변수 「」가 사용되고 있습니다.NO_OF_EMPLOYEES현재 회사에서 일하는 직원 수를 추적합니다. Employee 되며 그에합니다.「 Employee 」 。
employee_1 = Employee('Andrew', 'Brown', 85000)
print(f'Number of employees: {Employee.NO_OF_EMPLOYEES}')
employee_2 = Employee.employee_from_full_name('John Black', 95000)
print(f'Number of employees: {Employee.NO_OF_EMPLOYEES}')
Number of employees: 1
Number of employees: 2
정적 방식
인스턴스( 인스턴스)는 사용되지 않습니다.self 자체 클래스 자체)도 cls인 인수로 는 암묵적인 인수로 전달됩니다.즉, 이러한 메서드는 클래스 자체 또는 해당 인스턴스에 액세스할 수 없습니다.정적 메서드는 클래스의 멤버로 추가하는 대신 도우미 모듈에 배치할 수 있기 때문에 클래스의 컨텍스트에서는 유용하지 않다고 주장할 수 있습니다.객체 지향 프로그래밍에서는 클래스를 논리 청크로 구성하는 것이 중요합니다.따라서 정적 메서드는 단순히 논리적으로 클래스에 속하기 때문에 클래스 아래에 메서드를 추가해야 할 때 유용합니다.예에서는 ' 방법'이 '정적 방법'입니다.get_employee_legal_obligations_txt는 단순히 회사의 모든 직원의 법적 의무를 포함하는 문자열을 반환합니다.이 함수는 클래스 자체 또는 어떤 인스턴스와도 상호 작용하지 않습니다.다른 도우미 모듈에 배치될 수도 있지만 이 클래스와 관련된 것은 이 클래스뿐이므로 Employee 클래스에 배치해야 합니다.
정적 메서드는 클래스 자체에서 직접 액세스할 수 있습니다.
print(Employee.get_employee_legal_obligations_txt())
1. An employee must complete 8 hours per working day
2. ...
또는 클래스의 인스턴스:
employee_1 = Employee('Andrew', 'Brown', 85000)
print(employee_1.get_employee_legal_obligations_txt())
1. An employee must complete 8 hours per working day
2. ...
레퍼런스
언급URL : https://stackoverflow.com/questions/136097/difference-between-staticmethod-and-classmethod
'programing' 카테고리의 다른 글
| 문자열을 카본으로 변환 (0) | 2023.02.03 |
|---|---|
| 공격 가능한 PHP 함수 (0) | 2023.02.03 |
| OPTIMISE TABLE을 실행하여 테이블 조각 모음으로 퍼포먼스 향상 (0) | 2023.02.03 |
| JavaScript:사용자 브라우저가 Chrome인지 확인하는 방법 (0) | 2023.02.03 |
| PHP에서 @ 연산자를 사용하여 오류 억제 (0) | 2023.02.03 |