파이썬의 정적 메소드?


1719

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

ClassName.static_method()

답변:


2026

네의 사용 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으로 변경 : 함수 데코레이터 구문이 추가되었습니다.


15
@staticmethod첫 번째 self매개 변수 를 피할 수 있는데 왜 장식을 추가 하거나 함수 포인터를 사용 합니까? 글쎄, 다른 언어로 허용 되는 객체 a를 호출 할 수 a.your_static_method()는 없지만 어쨌든 나쁜 습관으로 간주되며 컴파일러는 항상 그것에 대해 경고합니다.
SomethingSomething

1
@staticmethod 데코레이터와 함께 Python 2.7.12를 사용하고 있습니다. 정의 된 첫 번째 정적 메소드를 호출 할 수 없습니다. 그 주지도 오류 : 형식 오류 : 'StaticMethod를'객체는 호출하지 않습니다
Supratim Samantray

최고 사만 트레이, 확실합니까? 여기서는 2.4 이후에 사용할 수 있다고 명확하게 명시되어 있기 때문 입니다.
realslimshanky

11
@SomethingSomething, 변수 이름 "self"를 사용하지 않고 데코레이터를 추가하지 않으면 첫 번째 인수, 예를 들어 arg1이 여전히 자체 인스턴스에 대한 참조가됩니다. self라는 이름은 컨벤션 일뿐입니다.
George Moutsopoulos

1
@GeorgeMoutsopoulos-일반적으로 동의했습니다. 그러나-어쨌든 ClassName.methodName()정적 인 것처럼 메소드를 호출 할 수 있으며 메소드 에는 self제공 되지 않습니다 . 당신이 말했듯이 또한이 메소드를 호출에, 그것은 여전히 가능할 것이다 ClassInstance.methodName(), 그리고 self관계없이 이름의 첫 번째 매개 변수로 제공됩니다.
SomethingSothinging

220

나는 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)

8
첫 번째 예제 (@staticmethod없이 클래스로 호출)는 Python 2.7에서 작동하지 않습니다. "TypeError : unbound 메소드 rollCall ()을 Dog 인스턴스와 함께 첫 번째 인수로 호출해야합니다 (대신 int 인스턴스를 가져옵니다)"
tba

2
작동하지 않습니다. Dog.rollCall (-1)과 rex.rollCall (-1) 모두 동일하게 반환TypeError: unbound method rollCall() must be called with Dog instance as first argument (got int instance instead)
Mittenchops

3
@MestreLion 나는 이것이 정적 및 인스턴스 메소드를 혼란시키고 하나가 다른 것처럼 보이기 때문에 이것이 큰 이점이 아니라고 생각합니다. 메소드가 정적임을 알고 있으면 정적 메소드로 액세스해야합니다. 메소드가 인스턴스를 필요로하지 않거나 사용하지 않는다는 사실은 메소드를 사용하는 어느 곳에서나 자명해야합니다. 난 항상 사용 T.my_static_method()또는 type(my_t_instance).my_static_method()이 명확 내가 정적 메소드를 호출하고 있습니다 것을 즉시 분명하게하기 때문에.
Asad Saeeduddin


54

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

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


파이썬 2.5.2에서는 작동하지 않습니다. class Dummy: def static1(): print "hello from static1" @staticmethod def static2(): print "hello from static2" Dummy.static2() Dummy.static1() 출력 : hello from static2 Traceback <가장 최근 호출> : <모듈>의 46 번째 줄 "ll.py"Dummy.static1 () TypeError : unbound method static1 ()은 더미 인스턴스와 함께 첫 번째 인수로 호출 됨 (아무것도 얻지 않음)
Mahori

7
수업 내에서는 작동하지 않습니다. 파이썬은 self당신이 지시하지 않는 한 첫 번째 인수로 전달할 것 입니다. (참조 : decorator)
Navin

9
실제로 이것은 2.7에서 잘못되었으며 3.X에서 합법적입니다 (3.2에서 잘 테스트 됨). 즉 , 2.7 이하의 @staticmethod 데코레이터가 없으면 클래스 컨텍스트에서 메소드를 호출 할 수 없습니다 . 3.2에서는 작동하고 self호출 방법에 따라 적절하게 참조 를 삽입합니다 . 테스트 케이스 : pastebin.com/12DDV7DB .
spinkus

2
기술적으로 정확하지만 끔찍한 솔루션입니다. staticmethod장식 하나는 클래스 인스턴스 (인스턴스에 대한 함수를 호출 할 때이 액 실패) 모두에 대한 함수를 호출 할 수있다.
Ethan Furman

점 표기법을 사용하여 객체의 다른 속성처럼 메소드를 호출 할 수 있습니다. class C: def callme(): print('called'); C.callme()
pouya

32

파이썬의 정적 메소드?

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

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'])

11

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

# 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

10

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

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를의 장식을.


1

따라서 정적 메서드는 클래스의 개체를 만들지 않고 호출 할 수있는 메서드입니다. 예를 들어 :-

    @staticmethod
    def add(a, b):
        return a + b

b = A.add(12,12)
print b

위의 예제에서 메소드 addA객체 이름이 아닌 클래스 이름으로 호출됩니다 .


-3

파이썬 정적 메소드는 두 가지 방법으로 만들 수 있습니다.

  1. staticmethod () 사용

    class Arithmetic:
        def add(x, y):
            return x + y
    # create add static method
    Arithmetic.add = staticmethod(Arithmetic.add)
    
    print('Result:', Arithmetic.add(15, 10))

산출:

결과 : 25

  1. @staticmethod 사용

    class Arithmetic:
    
    # create add static method
    @staticmethod
    def add(x, y):
        return x + y
    
    print('Result:', Arithmetic.add(15, 10))

산출:

결과 : 25


당신은 예를 제공의 방법으로 공유 하는 방법을 당신이 그것을 할 수 있습니다. 그 방법의 의미를 설명하지 않았습니다.
zixuan

-4

나는 때때로이 질문에 직면한다. 내가 좋아하는 유스 케이스와 예제는 다음과 같습니다.

jeffs@jeffs-desktop:/home/jeffs  $ python36
Python 3.6.1 (default, Sep  7 2017, 16:36:03) 
[GCC 6.3.0 20170406] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import cmath
>>> print(cmath.sqrt(-4))
2j
>>>
>>> dir(cmath)
['__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'acos', 'acosh', 'asin', 'asinh', 'atan', 'atanh', 'cos', 'cosh', 'e', 'exp', 'inf', 'infj', 'isclose', 'isfinite', 'isinf', 'isnan', 'log', 'log10', 'nan', 'nanj', 'phase', 'pi', 'polar', 'rect', 'sin', 'sinh', 'sqrt', 'tan', 'tanh', 'tau']
>>> 

cmath 객체에 상태가 없기 때문에 cmath 클래스의 객체를 만드는 것은 의미가 없습니다. 그러나 cmath는 어떤 방식 으로든 관련된 메서드 모음입니다. 위의 예에서 cmath의 모든 함수는 어떤 식 으로든 복잡한 숫자에 작용합니다.


질문에 대답하지 않았지만 대신 예를 제공했습니다.
zixuan
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.