prosource

'static method' 개체를 호출할 수 없습니다.

probook 2023. 10. 30. 21:03
반응형

'static method' 개체를 호출할 수 없습니다.

내가 가지고 있는 코드는 다음과.

class A(object):
    @staticmethod
    def open():
        return 123

    @staticmethod
    def proccess():
        return 456

    switch = {
        1: open,
        2: proccess,
    }


obj = A.switch[1]()

이 작업을 실행하면 계속 오류가 발생합니다.

TypeError: 'staticmethod' object is not callable

어떻게 해결해야 합니까?

바인딩되지 않은 상태로 저장하고 있습니다. staticmethod사전상의 사물이러한 객체(또한classmethod객체, 함수 및propertyobjects)는 클래스 또는 인스턴스의 속성으로 이름에 액세스하여 디스크립터 프로토콜을 통해서만 바인딩됩니다.직접 액세스하는 방법staticmethod클래스 본문의 개체는 속성 액세스 권한이 아닙니다.

클래스를 만든 사전을 만들거나(따라서 속성으로 액세스할 수 있습니다) 명시적으로 바인딩하거나, 사전에 저장하기 전에 원래 함수를 추출합니다.

에 대한 '구속력'에 유의하십시오.staticmethodobjects는 단지 문맥이 무시된다는 것을 의미합니다; bound.staticmethod기본 함수를 변경하지 않고 반환합니다.

따라서 속성을 사용하여 사전을 들여놓고 디스크립터 프로토콜을 트리거할 수 있습니다.

class A(object):
    @staticmethod
    def open():
        return 123
    @staticmethod
    def proccess():
        return 456

A.switch = {
    1: A.open,
    2: A.proccess,   
}

또는 더미 컨텍스트를 전달하여 명시적으로 바인딩하려면(어차피 무시될 것입니다):

class A(object):
    @staticmethod
    def open():
        return 123
    @staticmethod
    def proccess():
        return 456

    switch = {
        1: open.__get__(object),
        2: proccess.__get__(object),   
    }

또는 기본 기능에 직접 액세스할 수 있습니다.__func__특성:

class A(object):
    @staticmethod
    def open():
        return 123
    @staticmethod
    def proccess():
        return 456

    switch = {
        1: open.__func__,
        2: proccess.__func__,   
    }

그러나 여러 함수에 대한 네임스페이스만 제공하려는 경우 클래스 개체를 처음부터 사용해서는 안 됩니다.모듈에 기능을 넣습니다.당신이 사용할 필요가 없는 방법.staticmethod처음부터 장식품을 다시 포장을 풀 필요가 없습니다.

피터스의 대답 외에, 당신은 그냥 포기할 수 있습니다.@staticmethod:

class A(object):
    def open():
        return 123

    def proccess():
        return 456

    switch = {
        1: open,
        2: proccess,   
        }

obj = A.switch[1]()

하지만 이렇게 하면 전화하기가 불가능해집니다.open그리고.process와 함께self.

  • 클래스 밖에서 그들은 다음과 같이 호출될 수 있습니다.A.open()그리고.A.process(), 일반적인 정적 방법처럼 말입니다.
  • 교실 안에서 그들은 단지 그들과 함께 부를 수 있습니다.open()그리고.process(),없이.A..하지만,
    • A.open실패할 것입니다(나는 데코레이터 사용만으로 이 케이스를 테스트했습니다. (@open))
    • 게다가, 그것들은 그것들을 호출하는 기능보다 먼저 배치되어야 합니다.

단위 테스트용

Martijn답변 덕분에 그리고 그에 근거하여, 둘다__func__그리고.__get__(TestCase)테스트에서 정적 방법을 사용할 때 옵션이 잘 작동합니다. 예:

from unittest import TestCase, mock
from unittest.mock import MagicMock, Mock
class TestMother(TestCase):

    @staticmethod
    def side_effect_me(param: str) -> str:
        return param.capitalize()
    
    @mock.patch("src.some_folder.MyModule.my_func", \
        new=MagicMock(side_effect=side_effect_me.__func__))
    def test_should_cap(self):
        # test stuff

Python 3.10부터는 수용된 답변에 제시된 해결책이 더 이상 필요하지 않지만 여전히 작동합니다.

더욱이, 정적인 방법들은 이제 정규 함수로서 호출될 수 있습니다. (빅터 스티너가 bpo-43682에 기고함)

자세한 내용은 https://docs.python.org/3/whatsnew/3.10.html 을 참조하십시오.

Python 3.10.2
Type "help", "copyright", "credits" or "license" for more information.
>>> class A():
...     @staticmethod
...     def open():
...         return 123
...     @staticmethod
...     def process():
...         return 456
...     switch = {
...         1: open,
...         2: process
...     }
...
>>> A.switch[1]()
123
class A(object):
    def open():
        return 123

    def proccess():
        return 456

    switch = {
        1: lambda : A.open(),
        2: lambda : A.proccess(),   
        }

언급URL : https://stackoverflow.com/questions/41921255/staticmethod-object-is-not-callable

반응형