Python에서 정적 메서드를 사용하면 어떤 이점이 있습니까?


90

코드와 함께 파이썬에서 바인딩되지 않은 메서드 오류가 발생했습니다.

import random

class Sample(object):
'''This class defines various methods related to the sample'''

    def drawSample(samplesize,List):
        sample=random.sample(List,samplesize)
        return sample

Choices=range(100)
print Sample.drawSample(5,Choices)

여기에서 많은 유용한 게시물을 읽은 후 @staticmethod코드를 작동시키기 위해 위에 추가 할 수있는 방법을 찾았습니다 . 저는 파이썬 초보자입니다. 누군가 정적 메서드를 정의하려는 이유를 설명해 주시겠습니까? 아니면 왜 모든 메서드가 정적 메서드로 정의되지 않았습니까?


1
이것은 이상한 질문입니다. 정적 방법은 디자인의 필수 요소 입니다. "장점"이 아닙니다. 반드시 사용해야하기 때문에 사용합니다. 정적 메서드를 갖는 것은 클래스의 디자인 기능입니다. 처음에 어떤 정적 메서드가 있는지 묻고 있습니까? 나는 당신이 알아야 할 것을 더 명확하게 정의하기 위해 질문을 바꿀 수 있다고 생각합니다.
S.Lott

15
아니요, 그들이 무엇인지 알고 싶지 않았습니다. 내가 알고 싶었던 것은 왜 그것이 "필수"인가라는 것이 었는데, 이는 다른 사람들의 대답에서 분명해졌습니다. 이때 비 정적 메서드보다 정의 할 때입니다. 감사.
Curious2learn

3
@ S.Lott : 일반 클래스 메서드를 사용하는 것과 달리 정적 메서드를 사용해야하는 경우는 언제입니까? 내가 말할 수있는 한, 클래스 메소드는 staticmethod가 할 수있는 모든 것을 할 수 있습니다. Staticmethod는이 게시물의 다른 부분에 나열된 "장점"을 가지고 있지만 정적 메서드를 사용할 수있는 곳에서 클래스 메서드를 사용할 수없는 이유를 알 수 없으므로 필수입니다.
RFV

답변:


128

정적 메서드는 클래스의 인스턴스 속성에 액세스 할 수없고 (일반 메서드와 마찬가지로) 클래스 자체의 속성에 액세스 할 수 없기 때문에 사용이 제한됩니다. ).

따라서 일상적인 방법에는 유용하지 않습니다.

그러나 이들은 제공된 매개 변수 (및 모듈에 전역 적으로 일부 속성)와는 별도로 정보에 액세스 할 필요가없는 클래스 (예 : 한 유형에서 다른 유형으로의 간단한 변환)와 함께 일부 유틸리티 함수를 그룹화하는 데 유용 할 수 있습니다. )

클래스 외부에 둘 수 있지만 클래스 내부에 그룹화하면 해당 위치에서만 적용 할 수 있습니다.

또한 모듈 이름이 아닌 인스턴스 또는 클래스를 통해 메서드를 참조 할 수도 있습니다. 이렇게하면 독자가 메서드가 관련된 인스턴스를 이해하는 데 도움이 될 수 있습니다.


8
@ Curious2learn : 모든 것은 아니지만 일부 메서드는 정적 메서드로 유용합니다. Locale인스턴스가 로케일 (duh) 인 예제 클래스를 생각해보십시오 . getAvailableLocales()방법은 클래스의 정적 방법의 좋은 예가 될 것이다 : 그것을 명확하게 Locale 클래스에 속하는, 또한 명확하게 특정 인스턴스에 속해 있지 않습니다있다.
MestreLion

... 그리고 클래스의 메소드에 액세스 할 필요가 없기 때문에 클래스 메소드도 아닙니다.
MestreLion

정적 메서드는 것을 편집자 포인트 를 명시 적에서 아래로 이동하여, 클래스 속성에 접근 class_name.attribute, 그냥 cls.attributeself.attribute. 이것은 "공용"속성에 해당됩니다. 관례에 따라 이러한 방식으로 밑줄로 숨겨진 속성이나 두 개의 밑줄로 뭉쳐진 이름에 액세스해서는 안됩니다. 또한 속성이 상속 계층에서 위치를 이동할 때 코드가 더 취약해질 수 있음을 의미합니다.
Oddthinking

정적 메소드를 사용할시기를 결정하는 데 도움이되는 Guido의 인용문 (절대) : "우리 모두 정적 메소드가 얼마나 제한 된지 알고 있습니다. (기본적으로 우연입니다. 내가 새로운 스타일의 클래스와 설명자를 발명하던 Python 2.2 일 때) , 클래스 메서드를 구현하려고했지만 처음에는 이해하지 못했고 실수로 정적 메서드를 먼저 구현했습니다. 그런 다음이를 제거하고 클래스 메서드 만 제공하기에는 너무 늦었습니다. "
Boris Churzin

189

자세한 설명 은 이 기사 를 참조하십시오 .

TL; DR

1. self논쟁 의 사용을 제거합니다 .

2. Python은 시작된 각 개체에 대해 바인딩 된 메서드 를 인스턴스화 할 필요가 없기 때문에 메모리 사용량을 줄입니다 .

>>>RandomClass().regular_method is RandomClass().regular_method
False
>>>RandomClass().static_method is RandomClass().static_method
True
>>>RandomClass.static_method is RandomClass().static_method
True

3. 코드 가독성을 향상시켜 메서드가 객체 자체의 상태에 의존하지 않음을 나타냅니다.

4. 메서드가 모듈 수준 (즉, 클래스 외부)에서 정의 된 경우 하위 클래스가 해당 메서드를 재정의 할 수 없다는 점에서 메서드 재정의를 허용합니다.


3
이것은 받아 들여진 대답이어야합니다. 모든 인스턴스의 정적 메서드와 클래스 자체가 동일한 객체라는 사실은 특히 많은 인스턴스 (예 : 변경 가능한 데이터베이스 레코드에 대한 각 인스턴스)가있을 때 실제 이점입니다.
Zhuoyun Wei

+1하고 @ZhuoyunWei에 동의합니다. 정적 메서드가 클래스 메서드보다 때때로 선호되는 몇 가지 이유를 설명하는 유일한 답변입니다 (1과 3은 실제로 같은 이유 임).
Alex

1
"왜 정적 방법"에 대한 가장 좋은 대답이지만 원래의 질문은 "왜 모든 방법이 정적이 아닌가?"라는 질문을 던졌습니다. 짧은 "인스턴스 속성에 대한 액세스 권한 없음"도이를 다룹니다.
Exu

IMO의 유일한 진정한 장점은 하위 클래스에서 재정의 할 수 있다는 것입니다.하지만이 경우에도 OOP 방식으로 뭔가 잘못하고 있다는 느낌이 듭니다. 어떤 사용 사례에서 그렇게 하시겠습니까?
Boris Churzin

23

이것은 실제 질문의 요점은 아니지만 당신이 파이썬 초보자라고 말했기 때문에 아마도 도움이 될 것이며 다른 누구도 분명히 나와서 명시 적으로 말하지 않았습니다.

메서드를 정적 메서드로 만들어 위의 코드를 수정하지 않았을 것입니다. 클래스를 버리고 함수를 작성했을 것입니다.

def drawSample(samplesize,List):
    sample=random.sample(List,samplesize)
    return sample

Choices=range(100)
print drawSample(5,Choices)

관련 함수가 많으면 모듈로 그룹화 할 수 있습니다. 즉, sample.py예를 들어 이름이 같은 파일에 모두 넣습니다 . 그때

import sample

Choices=range(100)
print sample.drawSample(5,Choices)

또는 __init__클래스에 메서드를 추가하고 유용한 메서드가있는 인스턴스를 만들었습니다.

class Sample(object):
'''This class defines various methods related to the sample'''

    def __init__(self, thelist):
        self.list = thelist

    def draw_sample(self, samplesize):
        sample=random.sample(self.list,samplesize)
        return sample

choices=Sample(range(100))
print choices.draw_sample(5)

(또한 PEP 8에서 권장하는 스타일과 일치하도록 위의 예에서 대소 문자 규칙을 변경했습니다.)

파이썬의 장점 중 하나는 모든 것에 클래스를 사용하도록 강요하지 않는다는 것입니다. 클래스의 용도 인 메서드와 연결되어야하는 데이터 또는 상태가있는 경우에만 사용할 수 있습니다. 그렇지 않으면 기능을 사용할 수 있습니다.


댓글 주셔서 감사합니다. 이 경우에는 그려진 샘플로 작업하고 싶기 때문에 수업이 필요했습니다. 아니요 정적 방법을 사용하지 않았지만 오류 메시지에 대한 정보를 찾을 때 용어를 접했기 때문에 배우고 싶었습니다. 그러나 클래스를 정의하지 않고 함수를 모듈로 수집하는 것에 대한 귀하의 조언은 필요한 다른 함수에 도움이 될 것입니다. 감사합니다.
Curious2learn

4
+1 : OP의 오해에 대한 좋은 설명이었습니다. 그리고 당신은 당신이되었다는 것을, 선행 말을 아주 정직 하지 실제로 정적 방법에 대한 자신의 질문에 대답,하지만 당신은 오히려 훨씬 더 나은했다 솔루션을 자신의 문제가 전혀 클래스를 필요로하지 않는 말을.
MestreLion

22

정적 메서드를 정의하려는 이유는 무엇 입니까?

우리가이 있다고 가정 class이라는 Math다음

아무도의 객체를 생성 할 것 class Math
같은 방법 다음 호출 ceil하고 floor그리고 fabs거기에있다.

그래서 우리는 그들을 만듭니다 static.

예를 들어

>> Math.floor(3.14)

보다 훨씬 낫다

>> mymath = Math()
>> mymath.floor(3.14)

그래서 그들은 어떤면에서 유용합니다. 이를 사용하기 위해 클래스의 인스턴스를 만들 필요는 없습니다.

모든 메서드가 정적 메서드로 정의되지 않는 이유는 무엇 입니까?

인스턴스 변수에 액세스 할 수 없습니다.

class Foo(object):
    def __init__(self):
        self.bar = 'bar'

    def too(self):
        print self.bar

    @staticmethod
    def foo():
        print self.bar

Foo().too() # works
Foo.foo() # doesn't work

그렇기 때문에 모든 메서드를 정적으로 만들지 않습니다.


10
그러나 패키지 수학은 어떻습니까? Python에는이를위한 패키지가 있으므로 네임 스페이스를 생성하기 위해 클래스 정의가 필요 하지 않습니다 .
extraneon

6
@extraneon : 그래 친구 나는 그것을 알고 있지만 설명을 위해 간단하고 친숙한 것을 원했기 때문에 Math. 그것이 내가 대문자로 쓴 이유 M입니다.
Pratik Deoghare

6
OP는 정적 메소드가 무엇인지 묻지 않았습니다. 그는 그들의 장점이 무엇인지 물었습니다. 당신은 그것들이 어떻게 유용한 지 설명하는 것이 아니라 사용하는 방법을 설명하고 있습니다. 특정 예에서 네임 스페이스가 훨씬 더 의미가 있습니다.
Javier

4
-1 : 훌륭하고 정확한 설명이지만 매우 잘못 선택된 예 : Math처음에 클래스가 될 이유가 없습니다 . 모듈이 더 적합 할 것입니다. "아무도 객체를 만들고 싶어하지 않는" 클래스가 아닌 클래스로 이해되는 클래스의 예를 찾으십시오 .
MestreLion

3
그런 다음 클래스의 메서드 중 하나 (또는 일부 )가 정적 이지만 전부가 아닌 합법적 인 사용 사례의 예 제공 합니다 . 경우 모든 클래스 '방법은 정적, 클래스 모듈해야한다. 경우 아무도 정적 없습니다, 당신은 질문에 대답하지 않습니다.
MestreLion

13

객체 인스턴스에서 함수 객체를 호출하면 '바운드 메서드'가되고 인스턴스 객체 자체가 첫 번째 인수로 전달됩니다.

classmethod객체 인스턴스에서 객체 (함수 객체를 래핑) 를 호출 하면 인스턴스 객체의 클래스가 첫 번째 인수로 전달됩니다.

staticmethod객체 (함수 객체를 래핑) 를 호출 할 때 암시 적 첫 번째 인수가 사용되지 않습니다.

class Foo(object):

    def bar(*args):
        print args

    @classmethod
    def baaz(*args):
        print args

    @staticmethod
    def quux(*args):
        print args

>>> foo = Foo()

>>> Foo.bar(1,2,3)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unbound method bar() must be called with Foo instance as first argument (got int instance instead)
>>> Foo.baaz(1,2,3)
(<class 'Foo'>, 1, 2, 3)
>>> Foo.quux(1,2,3)
(1, 2, 3)

>>> foo.bar(1,2,3)
(<Foo object at 0x1004a4510>, 1, 2, 3)
>>> foo.baaz(1,2,3)
(<class 'Foo'>, 1, 2, 3)
>>> foo.quux(1,2,3)
(1, 2, 3)

3
+1 : 마지막으로 정적 메서드 클래스 메서드가 무엇인지에 대한 훌륭한 설명입니다 . 당신이 설명하지 않았지만 하나가 지금까지 정적 인 방법을 사용할 것, 적어도 당신은 분명 모두가 무엇을 간단한 예를 들어 설명 이다 훨씬 더 않는 공식 문서보다.
MestreLion

3

정적 메서드는 메서드가 속한 개체의 인스턴스를 선언 할 필요가 없기 때문에 훌륭합니다.

파이썬 사이트에는 정적 메서드에 대한 몇 가지 훌륭한 문서가 있습니다.
http://docs.python.org/library/functions.html#staticmethod


감사합니다 David. 그러나 인스턴스에서도 작동하므로 모든 메서드를 정적 메서드로 정의하지 않는 이유는 무엇입니까? 그렇게하면 단점이 있습니까?
Curious2learn

4
@ Curious2learn : 아니요, 정적 메서드를 사용하면 인스턴스에 액세스 할 수 없습니다 . 인스턴스는 해당 클래스를 제외하고 무시됩니다.
Felix Kling

4
이 인수는 Java에서 true이며, 함수는 자체적으로 존재할 수 없지만 항상 클래스 컨텍스트에서 정의됩니다. 그러나 Python에서는 함수와 정적 클래스 함수를 가질 수 있습니다. 이 답변은 클래스가 아닌 메서드 대신 정적 메서드를 선택하는 이유를 실제로 보여주지 않습니다.
extraneon

1
@extraneon-코드 구성 선호도의 문제입니다. 정적 메서드를 사용하면 추가 옵션이 제공됩니다.
Charles Duffy

@Felix-감사합니다. 이것은 모든 메서드가 정적 메서드가 아니어야하는 이유를 명확히합니다.
Curious2learn 2010 년

3

A와 대안은 staticmethod:입니다 classmethod, instancemethod하고 function. 이것이 무엇인지 모르는 경우 마지막 섹션으로 스크롤하십시오. a staticmethod가 이러한 대안 중 어느 것보다 낫다면 작성 목적에 따라 다릅니다.

Python 정적 메서드의 장점

  • 클래스 나 인스턴스의 속성이나 메서드에 액세스 할 필요가없는 staticmethod경우 a가 classmethod또는 instancemethod. 그렇게하면 ( @staticmethod데코레이터에서) 클래스와 인스턴스의 상태가 읽히거나 수정되지 않는다는 것이 분명해집니다 . 그러나 a를 function사용하면 구분이 더욱 명확 해집니다 (단점 참조).
  • a의 호출 서명은 staticmethoda classmethod또는 instancemethod, 즉 <instance>.<method>(<arguments>). 따라서 나중에 필요할 경우 또는 파생 클래스에서 세 가지 중 하나로 쉽게 대체 할 수 있습니다 . 간단한 function.
  • A staticmethod대신 A 를 사용 function하여 주관적으로 클래스에 속함을 확인하고 네임 스페이스 충돌을 방지 할 수 있습니다.

파이썬 정적 메서드의 단점

  • 인스턴스 또는 클래스의 속성이나 메서드에 액세스 할 수 없습니다.
  • a의 호출 서명 staticmethod은 a classmethod또는 의 호출 서명과 동일 instancemethod합니다. 이것은 staticmethod실제로 객체 정보를 읽거나 수정하지 않는다는 사실을 숨 깁니다 . 이것은 코드를 읽기 어렵게 만듭니다. 왜 사용하지 function않습니까?
  • A staticmethod는 정의 된 클래스 / 인스턴스 외부에서 호출해야하는 경우 재사용하기 어렵습니다. 재사용 가능성이있는 경우 a function가 더 나은 선택입니다.
  • staticmethod사람들이 하나 읽어 약간의 시간이 소요될 수 있습니다 포함 코드를 읽기 때문에 거의 사용되지 않는다.

Python의 정적 메서드에 대한 대안

의 장점에 대해 논의하려면 staticmethod대안이 무엇이며 서로 어떻게 다른지 알아야합니다.

  • staticmethod클래스에 속하지만 인스턴스 또는 클래스 정보에 액세스하거나 수정할 수 없습니다.

이에 대한 세 가지 대안이 있습니다.

  • classmethod호출 측의 클래스에 액세스 할 수 있습니다.
  • instancemethod발신자의 인스턴스와 해당 클래스에 액세스 할 수 있습니다.
  • function수업과는 아무 상관이 없습니다. 기능이 staticmethod.

코드에서 다음과 같이 표시됩니다.

# function
# has nothing to do with a class
def make_cat_noise(asker_name):
    print('Hi %s, mieets mieets!' % asker_name)

# Yey, we can make cat noises before we've even defined what a cat is!
make_cat_noise('JOey')  # just a function

class Cat:
    number_of_legs = 4

    # special instance method __init__
    def __init__(self, name):
        self.name = name

    # instancemethod
    # the instance (e.g. Cat('Kitty')) is passed as the first method argument
    def tell_me_about_this_animal(self, asker_name):
        print('Hi %s, This cat has %d legs and is called %s'
              % (asker_name, self.number_of_legs, self.name))

    # classmethod
    # the class (e.g. Cat) is passed as the first method argument
    # by convention we call that argument cls
    @classmethod
    def tell_me_about_cats(cls, asker_name):
        print("Hi %s, cats have %d legs."
              % (asker_name, cls.number_of_legs))
        # cls.name  # AttributeError because only the instance has .name
        # self.name  # NameError because self isn't defined in this namespace

    # staticmethod
    # no information about the class or the instance is passed to the method
    @staticmethod
    def make_noise(asker_name):
        print('Hi %s, meooow!' % asker_name)
        # class and instance are not accessible from here

# one more time for fun!
make_cat_noise('JOey')  # just a function

# We just need the class to call a classmethod or staticmethod:
Cat.make_noise('JOey')  # staticmethod
Cat.tell_me_about_cats('JOey')  # classmethod
# Cat.tell_me_about_this_animal('JOey')  # instancemethod -> TypeError

# With an instance we can use instancemethod, classmethod or staticmethod
mycat = Cat('Kitty')  # mycat is an instance of the class Cat
mycat.make_noise('JOey')  # staticmethod
mycat.tell_me_about_cats('JOey')  # classmethod
mycat.tell_me_about_this_animal('JOey')  # instancemethod

1

네임 스페이스 기능이 좋기 때문에 (이전에 지적했듯이) :

  1. 객체의 상태를 변경하지 않는 메서드를 명시하고 싶을 때는 정적 메서드를 사용합니다. 이것은 우리 팀의 사람들이 이러한 메서드에서 개체의 속성을 변경하기 시작하지 못하게합니다.

  2. 정말 썩은 코드를 리팩토링 할 때 @staticmethod가능한 한 많은 방법을 만드는 것부터 시작 합니다. 이렇게하면 이러한 메서드를 클래스로 추출 할 수 있습니다. 동의하지만이 방법은 거의 사용하지 않지만 몇 번 도움이되었습니다.


1

내 예상으로는 s 를 사용 하는 것보다 s 를 사용 하여 클래스 외부에서 함수를 정의하고 클래스와 분리하는 것과 비교할 때 단일 성능 이점 이 없습니다 .@staticmethod@staticmethod

그들의 존재를 정당화하는 유일한 것은 편의성입니다. 정적 메서드는 다른 인기있는 프로그래밍 언어에서 일반적입니다. 그렇다면 파이썬은 어떻습니까? 클래스와 매우 밀접하게 관련된 동작을 가진 함수를 만들고 싶지만 클래스 인스턴스의 내부 데이터를 일반적인 것으로 개념화하는 것을 정당화하는 방식으로 실제로 액세스 / 수정하지 않는 경우 그런 다음 해당 클래스의 메서드를 그 @staticmethod위에 두드리면 코드를 읽는 사람은 즉시 메서드의 특성과 클래스와의 관계에 대해 많은 것을 알게됩니다.

내가 가끔 좋아하는 한 가지는 내 클래스가 내부적으로 많이 사용하는 기능을 private에 배치하는 것 @staticmethod입니다. 이렇게하면 내 모듈을 사용하는 사람이 사용은 말할 것도없이 볼 필요가없는 메서드로 모듈에 의해 노출 된 API를 어지럽히 지 않습니다.


0

정적 메서드는 Python에있을 이유가 거의 없습니다. 인스턴스 메서드 또는 클래스 메서드를 사용합니다.

def method(self, args):
    self.member = something

@classmethod
def method(cls, args):
    cls.member = something

@staticmethod
def method(args):
    MyClass.member = something
    # The above isn't really working
    # if you have a subclass

당신은 "거의"라고 말했다. 대안보다 더 나을 수있는 곳이 있습니까?
Javier

@Javier : 하나는 생각할 수 없지만 아마도 하나가있을 것입니다. 그렇지 않으면 왜 그 메소드가 파이썬 라이브러리에 포함 될까요?
Georg Schölly

1
@Javier, @Georg : 파이썬 말뭉치가 엉망이되지 않는다는 큰 믿음을 가지고 있습니다.
Charles Merriam

-1 :이 답변은 존재하지 않는 어떤 사용하는 경우 staticmethod또는 어떤 A는 무엇의 설명 classmethod또는 왜하고 정적 인 것보다 "더 나은"방법입니다.
MestreLion

@CharlesMerriam : 물론 정적 메서드의 사용법이 있습니다. 그렇지 않으면 Python 3에서 삭제되거나 더 이상 사용되지 않을 것입니다 (대부분의 레거시 cruft가 제거됨). 문서에서 그것이 엉망이라는 주장을 뒷받침 하는 단 하나의 단어 staticmethodclassmethod대신 사용해야 하는 Georg의 주장 이 없습니다.)
MestreLion
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.