[python] 파이썬의 정적 메소드?

파이썬에서 정적 메소드를 사용하여 클래스를 초기화하지 않고 호출 할 수 있습니까?

ClassName.static_method()



답변

네의 사용 StaticMethod를 장식을

class MyClass(object):
    @staticmethod
    def the_static_method(x):
        print(x)

MyClass.the_static_method(2)  # outputs 2

일부 코드 staticmethod는 데코레이터 대신 함수로 사용하여 정적 메서드를 정의하는 이전 방법을 사용할 수 있습니다 . 이것은 고대 버전의 Python (2.2 및 2.3)을 지원 해야하는 경우에만 사용해야합니다

class MyClass(object):
    def the_static_method(x):
        print(x)
    the_static_method = staticmethod(the_static_method)

MyClass.the_static_method(2)  # outputs 2

이것은 @staticmethod멋진 데코레이터 구문을 사용하지 않고 첫 번째 예제와 완전히 동일합니다 (사용 )

마지막으로, staticmethod()드물게 사용하십시오! 파이썬에서 정적 메소드가 필요한 상황은 극히 적으며, 별도의 “최상위”함수가 더 명확했던 여러 번 사용 된 것을 보았습니다.


다음은 설명서의 내용입니다. :

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

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

@staticmethod 형식은 함수 데코레이터 입니다. 자세한 내용 은 함수 정의에서 함수 정의 설명을 참조 하십시오.

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

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

정적 방법에 대한 자세한 내용은의 표준 유형 계층에 대한 문서 참조 표준 유형 계층 구조를 .

버전 2.2의 새로운 기능

버전 2.4으로 변경 : 함수 데코레이터 구문이 추가되었습니다.


답변

나는 Steven이 실제로 옳다고 생각한다 . 원래 질문에 대답하려면 클래스 메소드를 설정하려면 첫 번째 인수가 호출 인스턴스가 아니라고 가정하고 클래스에서 메소드 만 호출해야합니다.

(이 답변은 Python 3.x를 나타냅니다. Python 2.x에서는 TypeError클래스 자체에서 메서드를 호출 할 수 있습니다.)

예를 들면 다음과 같습니다.

class Dog:
    count = 0 # this is a class variable
    dogs = [] # this is a class variable

    def __init__(self, name):
        self.name = name #self.name is an instance variable
        Dog.count += 1
        Dog.dogs.append(name)

    def bark(self, n): # this is an instance method
        print("{} says: {}".format(self.name, "woof! " * n))

    def rollCall(n): #this is implicitly a class method (see comments below)
        print("There are {} dogs.".format(Dog.count))
        if n >= len(Dog.dogs) or n < 0:
            print("They are:")
            for dog in Dog.dogs:
                print("  {}".format(dog))
        else:
            print("The dog indexed at {} is {}.".format(n, Dog.dogs[n]))

fido = Dog("Fido")
fido.bark(3)
Dog.rollCall(-1)
rex = Dog("Rex")
Dog.rollCall(0)

이 코드에서 “rollCall”메소드는 첫 번째 인수가 인스턴스가 아니라고 가정합니다 (클래스 대신 인스턴스가 호출 한 것처럼). “rollCall”이 인스턴스가 아닌 클래스에서 호출되는 한 코드는 정상적으로 작동합니다. 인스턴스에서 “rollCall”을 호출하려고하면 다음과 같이됩니다.

rex.rollCall(-1)

그러나 자체와 -1이라는 두 개의 인수를 보내므로 “rollCall”은 하나의 인수 만 허용하도록 정의되므로 예외가 발생합니다.

또한, rex.rollCall ()은 정확한 개수의 인수를 보내지 만, 함수가 n을 숫자로 기대할 때 n이 Dog 인스턴스 (즉, rex)를 나타내므로 예외가 발생합니다.

여기가 데코레이션이 온 곳입니다. “rollCall”메소드 앞에

@staticmethod

그런 다음 메소드가 정적임을 명시 적으로 명시하여 인스턴스에서 메소드를 호출 할 수도 있습니다. 지금,

rex.rollCall(-1)

작동 할 것이다. 메소드 정의 앞에 @staticmethod를 삽입하면 인스턴스가 인수로 전송되지 않습니다.

@staticmethod 줄을 주석 처리하지 않고 다음 코드를 시도하여이를 확인할 수 있습니다.

class Dog:
    count = 0 # this is a class variable
    dogs = [] # this is a class variable

    def __init__(self, name):
        self.name = name #self.name is an instance variable
        Dog.count += 1
        Dog.dogs.append(name)

    def bark(self, n): # this is an instance method
        print("{} says: {}".format(self.name, "woof! " * n))

    @staticmethod
    def rollCall(n):
        print("There are {} dogs.".format(Dog.count))
        if n >= len(Dog.dogs) or n < 0:
            print("They are:")
            for dog in Dog.dogs:
                print("  {}".format(dog))
        else:
            print("The dog indexed at {} is {}.".format(n, Dog.dogs[n]))


fido = Dog("Fido")
fido.bark(3)
Dog.rollCall(-1)
rex = Dog("Rex")
Dog.rollCall(0)
rex.rollCall(-1)


답변

예, 정적 메소드 데코레이터를 확인하십시오 .

>>> class C:
...     @staticmethod
...     def hello():
...             print "Hello World"
...
>>> C.hello()
Hello World


답변

실제로 @staticmethod데코레이터 를 사용할 필요는 없습니다 . 자체 매개 변수를 기대하지 않는 메서드를 선언하고 클래스에서 호출하면됩니다. 데코레이터는 인스턴스에서 호출 할 수있는 경우에만 있습니다 (원하는 것이 아니 었습니다)

대부분의 경우 함수를 사용합니다 …


답변

파이썬의 정적 메소드?

파이썬에서 정적 메소드를 가질 수 있으므로 클래스를 초기화하지 않고 호출 할 수 있습니다.

ClassName.StaticMethod()

예, 정적 메소드는 다음과 같이 작성할 수 있습니다 ( 메소드에 CamelCase 대신 밑줄을 사용 하는 것이 조금 더 Pythonic 임에도 불구하고 ).

class ClassName(object):

    @staticmethod
    def static_method(kwarg1=None):
        '''return a value that is a function of kwarg1'''

위는 데코레이터 구문을 사용합니다. 이 구문은

class ClassName(object):

    def static_method(kwarg1=None):
        '''return a value that is a function of kwarg1'''

    static_method = staticmethod(static_method)

이것은 당신이 설명한대로 사용할 수 있습니다 :

ClassName.static_method()

정적 메소드의 내장 예제는 str.maketrans()Python 3에 있으며, 이는 stringPython 2 의 모듈에 있는 함수입니다 .


설명 할 때 사용할 수있는 또 다른 옵션 classmethod은입니다. 차이점은 classmethod가 클래스를 암시 적 첫 번째 인수로 가져오고 서브 클래스 화하면 하위 클래스를 암시 적 첫 번째 인수로 가져옵니다.

class ClassName(object):

    @classmethod
    def class_method(cls, kwarg1=None):
        '''return a value that is a function of the class and kwarg1'''

참고 cls첫 번째 인수의 필수 이름이 아닙니다,하지만 당신은 무엇을 사용하는 경우 가장 경험이 풍부한 파이썬 코더가 심하게 이루어 고려할 것입니다.

이들은 일반적으로 대체 생성자로 사용됩니다.

new_instance = ClassName.class_method()

내장 된 예는 dict.fromkeys()다음과 같습니다.

new_dict = dict.fromkeys(['key1', 'key2'])


답변

정적 메서드 객체의 작동 방식 과는 별도로 모듈 수준 코드를 구성 할 때 어떤 종류의 아름다움을 느낄 수 있습니다.

# garden.py
def trim(a):
    pass

def strip(a):
    pass

def bunch(a, b):
    pass

def _foo(foo):
    pass

class powertools(object):
    """
    Provides much regarded gardening power tools.
    """
    @staticmethod
    def answer_to_the_ultimate_question_of_life_the_universe_and_everything():
        return 42

    @staticmethod
    def random():
        return 13

    @staticmethod
    def promise():
        return True

def _bar(baz, quux):
    pass

class _Dice(object):
    pass

class _6d(_Dice):
    pass

class _12d(_Dice):
    pass

class _Smarter:
    pass

class _MagicalPonies:
    pass

class _Samurai:
    pass

class Foo(_6d, _Samurai):
    pass

class Bar(_12d, _Smarter, _MagicalPonies):
    pass

# tests.py
import unittest
import garden

class GardenTests(unittest.TestCase):
    pass

class PowertoolsTests(unittest.TestCase):
    pass

class FooTests(unittest.TestCase):
    pass

class BarTests(unittest.TestCase):
    pass

# interactive.py
from garden import trim, bunch, Foo

f = trim(Foo())
bunch(f, Foo())

# my_garden.py
import garden
from garden import powertools

class _Cowboy(garden._Samurai):
    def hit():
        return powertools.promise() and powertools.random() or 0

class Foo(_Cowboy, garden.Foo):
    pass

이제는 특정 구성 요소가 사용되는 맥락에서 좀 더 직관적이고 자체 문서화되며, 테스트 테스트의 이름을 지정하는 데 이상적으로 적합하며 테스트 모듈이 순수 테스트를 위해 실제 모듈에 매핑되는 방법에 대한 직접적인 접근 방식을 갖습니다. .

프로젝트의 유틸리티 코드를 구성하는 데이 방법을 적용 할 수있는 경우가 종종 있습니다. 종종 사람들은 즉시 서두르고 utils패키지를 만들고 그 중 하나는 120 개의 LOC를 갖고 나머지는 최대 24 개의 LOC 인 9 개의 모듈로 끝납니다. 나는 이것을 시작하여 패키지로 변환하고 진정으로 가치가있는 짐승만을위한 모듈을 만드는 것을 선호합니다.

# utils.py
class socket(object):
    @staticmethod
    def check_if_port_available(port):
        pass

    @staticmethod
    def get_free_port(port)
        pass

class image(object):
    @staticmethod
    def to_rgb(image):
        pass

    @staticmethod
    def to_cmyk(image):
        pass


답변

아마도 가장 간단한 옵션은 해당 함수를 클래스 외부에 두는 것입니다.

class Dog(object):
    def __init__(self, name):
        self.name = name

    def bark(self):
        if self.name == "Doggy":
            return barking_sound()
        else:
            return "yip yip"

def barking_sound():
    return "woof woof"

이 방법을 사용하면 내부 객체 상태를 수정하거나 사용하는 기능 (부작용이 있음)을 클래스에 유지하고 재사용 가능한 유틸리티 기능을 외부로 이동할 수 있습니다.

이 파일이이라고하자 dogs.py. 이것을 사용하려면 dogs.barking_sound()대신에 전화하십시오 dogs.Dog.barking_sound.

당신이 정말로 클래스의 일부가 될 정적 방법을해야하는 경우 사용할 수 있습니다 StaticMethod를의 장식을.