[python] 정적 메소드와 클래스 메소드의 차이점

함수 장식의 차이 무엇 @staticmethod하나는 장식은 @classmethod?



답변

의 호출 서명에 공지 사항을 차이를 : 어쩌면 예제 코드의 약간의 도움이 될 것입니다 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않고 클래스가, A바인딩됩니다 class_foo.

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

정적 메소드를 사용하는 경우 여기에서는 메소드이지만 a.static_foo인수가 바인딩되지 않은 우수한 ‘ole 함수를 반환합니다. static_foo1 개의 인수를
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를가 가에 호출 된 클래스 또는 인스턴스에 대해 아무것도 알고하는 방법입니다. 전달 된 인수를 얻습니다. 암시 적 첫 번째 인수는 없습니다. 파이썬에서는 기본적으로 쓸모가 없습니다. 정적 메소드 대신 모듈 함수를 사용할 수 있습니다.

반면에 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암시 적 인수가 없습니다.


답변

공식 파이썬 문서 :

@classmethod

클래스 메서드는 인스턴스 메서드가 인스턴스를받는 것처럼 클래스를 암시 적 첫 번째 인수로받습니다. 클래스 메소드를 선언하려면 다음 관용구를 사용하십시오.

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

@classmethod형태의 함수이다
장식 – 함수의 정의에 대한 설명을 참조 함수 정의 자세한.

클래스 (등 C.f()) 또는 인스턴스 (등) 에서 호출 할 수 있습니다 C().f(). 클래스를 제외하고 인스턴스는 무시됩니다. 파생 클래스에 대해 클래스 메서드가 호출되면 파생 클래스 개체가 암시 적 첫 번째 인수로 전달됩니다.

클래스 메소드는 C ++ 또는 Java 정적 메소드와 다릅니다. 원하는 staticmethod()경우이 섹션을 참조하십시오 .

static

정적 메소드는 내재 된 첫 번째 인수를받지 않습니다. 정적 메소드를 선언하려면 다음 관용구를 사용하십시오.

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

@staticmethod형태의 함수이다
장식 – 함수의 정의에 대한 설명을 참조 함수 정의 자세한.

클래스 (등 C.f()) 또는 인스턴스 (등) 에서 호출 할 수 있습니다 C().f(). 클래스를 제외하고 인스턴스는 무시됩니다.

Python의 정적 메소드는 Java 또는 C ++에서 발견되는 메소드와 유사합니다. 고급 개념에 대해서는 classmethod()이 섹션을 참조하십시오
.


답변

다음은 이 질문에 짧은 기사입니다

@staticmethod 함수는 클래스 안에 정의 된 함수일뿐입니다. 클래스를 먼저 인스턴스화하지 않고 호출 할 수 있습니다. 상속을 통해 정의를 변경할 수 없습니다.

@classmethod 함수는 클래스를 인스턴스화하지 않고도 호출 할 수 있지만 그 정의는 상속을 통해 Parent 클래스가 아닌 Sub 클래스를 따릅니다. @classmethod 함수의 첫 번째 인수는 항상 cls (class) 여야하기 때문입니다.


답변

@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


답변

파이썬에서 @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. 이를 ” 인스턴스 메소드 “라고합니다. 인스턴스 메소드가 사용될 때, 부분 함수 (소스 코드에서 볼 때 모든 값에 대해 정의 된 총 함수와 반대)로 사용됩니다. 즉, 사용될 때 첫 번째 인수는 주어진 속성을 가진 객체. 개체의 인스턴스가 바인딩되어 있으며 개체의 인스턴스에서 호출되어야합니다. 일반적으로 인스턴스의 다양한 속성에 액세스합니다.

예를 들어 다음은 문자열의 인스턴스입니다.

', '

join이 문자열 에서 인스턴스 메소드를 사용하여 다른 iterable을 결합하는 경우 iterable 목록의 함수 외에도 인스턴스의 함수입니다 ['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'

정적 방법

정적 메소드는 인스턴스를 인수로 사용하지 않습니다 .

모듈 수준 기능과 매우 유사합니다.

그러나 모듈 레벨 기능은 모듈에 상주해야하며 모듈이 사용되는 다른 곳으로 특별히 가져와야합니다.

그러나 객체에 첨부 된 경우 가져 오기 및 상속을 통해 편리하게 객체를 따릅니다.

정적 메소드의 예는 str.maketrans, stringPython 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}

파이썬 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 소스 코드 를 참조하십시오 . classmethod및 공식 Python 문서도 참조하십시오 staticmethod.