program story

파이썬의 정적 / 클래스 변수에 대한 __getattr__

inputbox 2020. 12. 12. 10:40
반응형

파이썬의 정적 / 클래스 변수에 대한 __getattr__


다음과 같은 수업이 있습니다.

class MyClass:
     Foo = 1
     Bar = 2

때마다 MyClass.Foo또는 MyClass.Bar호출, 나는 값이 반환되기 전에 호출 될 사용자 정의 방법이 필요합니다. 파이썬에서 가능합니까? 클래스의 인스턴스를 만들고 자체 __getattr__메서드를 정의 할 수 있으면 가능하다는 것을 알고 있습니다 . 그러나 내 시나리오는 인스턴스를 생성하지 않고이 클래스를 그대로 사용하는 것과 관련이 있습니다.

또한 __str__호출 될 때 호출 할 사용자 지정 메서드가 필요합니다 str(MyClass.Foo). 파이썬이 그러한 옵션을 제공합니까?


__getattr__()__str__()개체에 대한 그래서 당신은 클래스 그 일을 사용자 정의하려는 경우, 당신은 클래스의-A-클래스가 필요, 동급에서 찾을 수 있습니다. 메타 클래스.

class FooType(type):
    def _foo_func(cls):
        return 'foo!'

    def _bar_func(cls):
        return 'bar!'

    def __getattr__(cls, key):
        if key == 'Foo':
            return cls._foo_func()
        elif key == 'Bar':
            return cls._bar_func()
        raise AttributeError(key)

    def __str__(cls):
        return 'custom str for %s' % (cls.__name__,)

class MyClass:
    __metaclass__ = FooType

# in python 3:
# class MyClass(metaclass=FooType):
#    pass


print MyClass.Foo
print MyClass.Bar
print str(MyClass)

인쇄:

foo!
bar!
custom str for MyClass

그리고 객체는 속성 중 하나를 문자열 화하기위한 요청을 가로 챌 수 없습니다. 속성에 대해 반환 된 개체는 자체 __str__()동작을 정의해야합니다 .


(나는 이것이 오래된 질문이라는 것을 알고 있지만 다른 모든 답변은 메타 클래스를 사용하기 때문에 ...)

다음과 같은 간단한 classproperty설명자를 사용할 수 있습니다 .

class classproperty(object):
    """ @classmethod+@property """
    def __init__(self, f):
        self.f = classmethod(f)
    def __get__(self, *a):
        return self.f.__get__(*a)()

다음과 같이 사용하십시오.

class MyClass(object):

     @classproperty
     def Foo(cls):
        do_something()
        return 1

     @classproperty
     def Bar(cls):
        do_something_else()
        return 2

첫 번째로, 메타 클래스를 만들고이를 정의 __getattr__()해야합니다.

class MyMetaclass(type):
  def __getattr__(self, name):
    return '%s result' % name

class MyClass(object):
  __metaclass__ = MyMetaclass

print MyClass.Foo

두 번째는 아닙니다. 호출 str(MyClass.Foo)하면을 호출 MyClass.Foo.__str__()하므로에 대한 적절한 유형을 반환해야합니다 MyClass.Foo.


놀랍게도 아무도 이것을 지적하지 않았습니다.

class FooType(type):
    @property
    def Foo(cls):
        return "foo!"

    @property
    def Bar(cls):
        return "bar!"

class MyClass(metaclass=FooType):
    pass

공장:

>>> MyClass.Foo
'foo!'
>>> MyClass.Bar
'bar!'

(Python 2.x의 경우 정의 MyClass를 다음으로 변경하십시오 .

class MyClass(object):
    __metaclass__ = FooType

)

str이 솔루션 에 대해 다른 답변이 말하는 것은 사실입니다. 실제로 반환되는 유형에서 구현되어야합니다.


Depending on the case I use this pattern

class _TheRealClass:
    def __getattr__(self, attr):
       pass

LooksLikeAClass = _TheRealClass()

Then you import and use it.

from foo import LooksLikeAClass
LooksLikeAClass.some_attribute

This avoid use of metaclass, and handle some use cases.

참고URL : https://stackoverflow.com/questions/3155436/getattr-for-static-class-variables-in-python

반응형