2010-03-13 11 views
51

나는 내가 작업 코드를 얻으려면 위의 @staticmethod 추가 할 수있는 방법을 생각, 여기에 많은 도움이 게시물을 읽은 후 코드파이썬에서 정적 메서드를 사용하면 어떤 이점이 있습니까?

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) 

와 파이썬에서 언 바운드 방법의 오류에 달렸다. 나는 파이썬 초보자이다. 정적 메서드를 정의하려는 이유를 설명해 줄 수 있습니까? 또는 모든 메소드가 정적 메소드로 정의되지 않은 이유는 무엇입니까?

+1

이것은 이상한 질문입니다. 정적 방법은 디자인 * 필수 *입니다. 그것은 "유리한"것이 아닙니다. 당신이해야하기 때문에 그들을 사용합니다. 정적 메소드를 가지는 것은 클래스의 디자인 기능입니다. 정적 방법이 무엇인지 처음부터 묻고 있습니까? 나는 당신이 알아야 할 것을 더 명확하게 정의하기 위해이 질문을 다시 쓸 수 있다고 생각한다. –

+9

아니요, 나는 그들이 무엇인지 알고 싶지 않았습니다. 제가 알고 싶었던 것은 왜 그것이 "필요성"인지, 다른 사람들이 준 응답에서 분명 해졌다는 것입니다. 정적이 아닌 메서드가 아닌 언제 정의 할 것입니다. 감사. – Curious2learn

답변

61

정적 방법은 사용이 제한, 그들은 클래스의 속성에 액세스 할 수 없습니다 그 자체가 (클래스 메소드가하는 것처럼).

그래서 일상적인 방법으로는 유용하지 않습니다.

그러나 일부 유틸리티 기능을 클래스와 함께 그룹화하는 것이 유용 할 수 있습니다. 한 유형에서 다른 유형으로의 간단한 변환 - 제공되는 매개 변수 (및 아마도 모듈의 전역 속성) 이외의 정보에 대한 액세스가 필요하지 않습니다.

클래스 외부에 배치 할 수 있지만 내부에 그룹화 할 수 있습니다 수업은 거기서 만 적용 할 수있는 곳에서 이해할 수 있습니다.

모듈 이름이 아닌 인스턴스 나 클래스를 통해 메서드를 참조 할 수도 있습니다.이 메서드는 메서드가 어떤 인스턴스에 관련되어 있는지 이해하는 데 도움이 될 수 있습니다.

+0

감사합니다. 이것은 모든 메소드가 정적 메소드가되어서는 안되는 이유를 명확히합니다. – Curious2learn

+2

@ Curious2learn : 모든 *가 아닌 * 일부 * 방법은 정적 방법으로 유용합니다. 인스턴스가 로케일 (duh)이 될'Locale' 클래스에 대해 생각해보십시오. 'getAvailableLocales()'메쏘드는 그러한 클래스의 정적 메쏘드에 대한 좋은 예가 될 것입니다 : 분명히 Locale 클래스에 속하는 반면 분명히 특정 인스턴스에 속하지는 않습니다. – MestreLion

+0

... 클래스 메소드에 액세스 할 필요가 없으므로 클래스 메소드가 아닙니다. – MestreLion

4

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

파이썬의 사이트는 여기 정적 방법에 대한 몇 가지 좋은 문서가 있습니다
http://docs.python.org/library/functions.html#staticmethod

+0

데이비드에게 감사드립니다. 그렇다면 왜 모든 메소드를 정적 메소드로 정의하지 않는가? 왜냐하면 그것들은 인스턴스에서도 작동하기 때문이다. 그렇게하는 데 단점이 있습니까? – Curious2learn

+4

@ Curious2learn : 아니요, 정적 메소드를 사용하면 인스턴스에 대한 액세스 권한이 없습니다. * 인스턴스는 해당 클래스를 제외하고 무시됩니다. * –

+4

자바에서는 함수가 자체적으로 살아갈 수 없지만 항상 정의됩니다. 클래스의 문맥. 하지만 파이썬에서는 함수와 정적 클래스 함수를 가질 수 있습니다. 이 대답은 실제로 클래스에없는 메소드 대신 정적 메소드를 선택하는 이유를 보여주지 않습니다. – extraneon

0

정적 방법이 거의 이유 --수에 파이썬이 없습니다. 인스턴스 메서드 또는 클래스 메서드를 사용합니다.

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 
+0

당신은 "거의"라고 말했습니다. 그들이 대안보다 더 좋은 곳이 있을까요? – Javier

+0

@Javier : 나는 하나를 생각할 수는 없지만, 아마도 그 중 하나가있을 것입니다. 그렇지 않으면 그 방법이 파이썬 라이브러리에 왜 포함될 것입니까? –

+0

@Javier, @Georg : 파이썬 코퍼스에는 크래프트가 없다는 것은 큰 신념입니다. –

11

왜 하나는 정적 메소드를 정의 할 것인가? 가정하자

우리는 class 다음

아무도 class Math
의 객체를 생성 한 후 ceilfloor 그것에 fabs 같은 메소드를 호출 할 것 Math라고합니다.

그래서 우리는 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 

그래서 우리는 모든 방법을 정적으로 만들지 않습니다.

+5

하지만 패키지 수학이 아닌 이유는 무엇입니까? 파이썬에는이 패키지가 포함되어 있으므로 네임 스페이스를 만들기 위해 클래스 정의를 _ 필요하지 않습니다. – extraneon

+5

@extraneon : 그래, 알았어. 나는 그걸 알고있다. 그러나 나는 설명을 위해 간단하고 익숙한 것을 갖고 싶었고, 그래서 나는 수학을 사용했다. 그것이 내가'M'을 대문자로 사용한 이유입니다. –

+6

OP는 정적 메서드가 무엇인지 묻지 않았습니다. 그는 자신의 장점을 물었다. 당신은 그들을 어떻게 사용 하는지를 설명하고 있습니다. 특정 예에서 네임 스페이스가 훨씬 더 적합합니다. – Javier

12

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

개체 인스턴스에서 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

14

이것은 실제 질문의 요점은 아니지만 여러분이 파이썬 초보자라고 말했기 때문에 아마도 도움이 될 것이고 아무도 꽤 나오지 않고 명시 적으로 말한 적이 없습니다.

나는이 메서드를 정적 메서드로 만들어서 위의 코드를 수정하지 못했을 것입니다. 나도 클래스를 도랑 단지 기능을 쓴 것 : 모듈에

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) 

아니면 내가 클래스에 초기화 방법을 추가하고 유용한 방법이 있었다 인스턴스를 만든 것 (나는 또한 일치하도록 위의 예에서 경우 규칙을 변경

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에서 권장하는 스타일)

파이썬의 장점 중 하나는 모든 것을 위해 클래스를 사용해야한다는 것입니다. 메소드와 연관되어야하는 데이터 또는 상태가있을 때만 사용할 수 있습니다. 이는 클래스가 사용하는 것입니다. 그렇지 않으면 함수가 사용할 함수를 사용할 수 있습니다.

+0

코멘트 주셔서 감사합니다. 나는 그려진 견본을 가지고 일하기를 원하기 때문에이 경우에는 반을 필요로했다. 정적 메소드를 사용하지 않았지만 알기를 원했습니다. 오류 메시지에 대한 정보를 찾을 때 용어를 접하게 되었기 때문입니다. 하지만 클래스를 정의하지 않고 함수를 모듈로 수집하는 것에 대한 조언은 내가 필요로하는 다른 함수에 도움이 될 것입니다. 감사합니다. – Curious2learn

+2

+1 : 그것은 OP가 가진 몇 가지 오해에 대한 좋은 설명이었습니다. 그리고 선생님은 정적 방법에 대한 그의 질문에 실제로 대답하지 않으 셨다는 것을 매우 솔직하게 말했지만, 당신은 오히려 그의 문제가 수업을 전혀 필요로하지 않는다고 말하는 훨씬 더 나은 해결책을 제시했습니다. – MestreLion

83

자세한 내용은 this article을 참조하십시오.

TL; DR

1.It는 self 인자의 사용을 제거한다.

>>>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.It이 방법은 상태에 의존하지 않는 것을 나타내는 코드 가독성 효과 : 파이썬 instiantiated 각 오브젝트의 bound-method를 초기화 할 필요가 없기 때문에

는 2.It 메모리 사용을 줄일 개체 자체.

4. 메소드가 모듈 수준 (즉, 클래스 외부)에 정의 된 경우 하위 클래스는 해당 메소드를 재정의 할 수 없으므로 메소드 재정의를 허용합니다.기능의 네임 것은 (이전에 지적 된 바와 같이) 좋은이기 때문에

+2

가장 많이 투표 된 답변이어야합니다! 감사! –

+0

이것은 허용 된 대답이어야합니다. 모든 인스턴스와 클래스 자체의 정적 메소드가 동일한 객체라는 사실은 특히 많은 인스턴스 (예 : 변경 가능한 데이터베이스 레코드의 각 인스턴스)가있는 경우 실질적인 이점입니다. –

0

는 :

  1. 나는 개체의 상태를 변경하지 않는 방법에 대한 명시 할 때, 나는 정적 인 방법을 사용합니다. 이는 팀원들이 이러한 방법으로 객체의 속성을 변경하는 것을 저지합니다.

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

0

은 그냥 그렇지 않으면 @staticmethod의 될 것이다 클래스에서 외부 함수를 정의하고 별도의 비교 @staticmethod의를 사용하는 단일 성능 혜택이 없습니다.

자신의 존재를 정당화하는 유일한 점은 편의입니다. 정적 메소드는 다른 유명한 프로그래밍 언어에서 흔히 볼 수있는 것이므로 파이썬이 아닌 이유는 무엇입니까? 클래스와 매우 밀접한 관련이있는 비헤이비어로 함수를 만들려하지만 클래스의 인스턴스에 대한 내부 데이터를 실제로 개념적으로 일반적인 것으로 정당화하는 방식으로 액세스/수정하지는 않습니다 그 클래스의 메소드는 그 다음에 @staticmethod을 치고 코드를 읽는 모든 사람들은 메소드의 본질과 클래스와의 관계에 대해 많은 것을 즉시 배우게됩니다.

때때로 내가 좋아하는 한 가지는 내 수업에서 내부적으로 많이 사용하는 장소 기능 인 개인 @staticmethod입니다. 그런 식으로 내 모듈에 노출 된 API를 혼란스럽게하지 않고 내 모듈을 사용하는 아무도 혼자 사용하지 않아도되는 메소드를 사용하지 않습니다.

관련 문제