복붙노트

[PYTHON] Python : 클래스를 반복 가능하게 만든다.

PYTHON

Python : 클래스를 반복 가능하게 만든다.

클래스 객체 (정수, 문자열 등) 만 구성하는 많은 큰 클래스를 가진 프로젝트를 상속 받았습니다. 나는 수동으로 속성 목록을 정의 할 필요없이 속성이 있는지 확인할 수 있기를 원합니다.

python 클래스를 표준 구문을 사용하여 iterable로 만들 수 있습니까? 즉, 클래스의 인스턴스를 먼저 만들 필요없이 Foo의 attr (또는 Foo의 attr 인 경우에도)을 사용하여 모든 클래스 속성을 반복 할 수 있기를 바랍니다. 나는 __iter__를 정의함으로써 이것을 할 수 있다고 생각하지만 지금까지 나는 내가 원하는 것을 관리하지 못했다.

나는 다음과 같이 __iter__ 메쏘드를 추가하여 원하는 것을 얻었습니다 :

class Foo:
    bar = "bar"
    baz = 1
    @staticmethod
    def __iter__():
        return iter([attr for attr in dir(Foo) if attr[:2] != "__"])

그러나 이것은 내가 찾고있는 것을 성취하지 못한다.

그럼에도 불구하고, 이것은 작동합니다 :

해결법

  1. ==============================

    1.클래스 자체 대신 __iter__를 메타 클래스에 추가하십시오 (Python 2.x로 가정).

    클래스 자체 대신 __iter__를 메타 클래스에 추가하십시오 (Python 2.x로 가정).

    class Foo(object):
        bar = "bar"
        baz = 1
        class __metaclass__(type):
            def __iter__(self):
                for attr in dir(Foo):
                    if not attr.startswith("__"):
                        yield attr
    

    Python 3.x에서는 다음을 사용하십시오.

    class MetaFoo(type):
        def __iter__(self):
            for attr in dir(Foo):
                if not attr.startswith("__"):
                    yield attr
    
    class Foo(metaclass=MetaFoo):
        bar = "bar"
        baz = 1
    
  2. ==============================

    2.attr (elem은 elem (: 2)! = '__'이면 elem in dir (Foo)의 elem을 사용하여 클래스의 숨김 속성을 반복 할 수 있습니다.

    attr (elem은 elem (: 2)! = '__'이면 elem in dir (Foo)의 elem을 사용하여 클래스의 숨김 속성을 반복 할 수 있습니다.

    덜 끔찍한 방법은 다음과 같습니다.

    def class_iter(Class):
        return (elem for elem in dir(Class) if elem[:2] != '__')
    

    그때

    for attr in class_iter(Foo):
        pass
    
  3. ==============================

    3.이것은 우리가 클래스 객체를 반복 가능하게 만드는 방법이다. 클래스에 iter 및 next () 메서드를 제공하면 클래스 속성이나 해당 값을 반복 할 수 있습니다. 원하는 경우 next () 메서드를 그대로 두거나 next ()를 정의하고 StopIteration을 일부 조건으로 올릴 수 있습니다 .

    이것은 우리가 클래스 객체를 반복 가능하게 만드는 방법이다. 클래스에 iter 및 next () 메서드를 제공하면 클래스 속성이나 해당 값을 반복 할 수 있습니다. 원하는 경우 next () 메서드를 그대로 두거나 next ()를 정의하고 StopIteration을 일부 조건으로 올릴 수 있습니다 .

    예 :

    class Book(object):
          def __init__(self,title,author):
              self.title = title
              self.author = author
    
          def __iter__(self):
              for each in self.__dict__.keys():
                  yield self.__getattribute__(each)
    
    >>> book  = Book('The Mill on the Floss','George Eliot')
    >>> for each in book: each
    ...
    'George Eliot'
    'The Mill on the Floss'
    

    이 클래스는 Book 클래스의 속성 값을 반복 처리합니다. 클래스 객체는 getitem 메소드도 제공하여 반복 가능하게 만들 수 있습니다. 예 :

    class BenTen(object):
        def __init__(self, bentenlist):
            self.bentenlist = bentenlist
    
        def __getitem__(self,index):
            if index <5:
                return self.bentenlist[index]
            else:
                raise IndexError('this is high enough')
    
    >>> bt_obj = BenTen([x for x in range(15)])
    >>>for each in bt_obj:each
    ...
    0
    1
    2
    3
    4
    

    이제 BenTen 클래스의 객체가 for-in 루프에서 사용될 때 getitem이 IndexError를 발생시킬 때까지 더 높은 인덱스 값으로 호출됩니다.

  4. ==============================

    4.Python 3.4 이상에서는 enum.Enum을 사용하여 반복 가능한 클래스를 만드는 것이 약간 쉽습니다.

    Python 3.4 이상에서는 enum.Enum을 사용하여 반복 가능한 클래스를 만드는 것이 약간 쉽습니다.

    from enum import Enum
    
    class Foo(Enum):
        bar = "qux"
        baz = 123
    
    >>> print(*Foo)
    Foo.bar Foo.baz
    
    names = [m.name for m in Foo]
    >>> print(*names)
    bar baz
    
    values = [m.value for m in Foo]
    print(*values)
    >>> qux 123
    
  5. ==============================

    5.

    class MetaItetaror(type):
        def __iter__(cls):
            return iter(
                filter(
                    lambda k: not k[0].startswith('__'),
                    cls.__dict__.iteritems()
                )
            )
    
    
    class Klass:
        __metaclass__ = MetaItetaror
    
        iterable_attr_names = {'x', 'y', 'z'}
        x = 5
        y = 6
        z = 7
    
    
    for v in Klass:
        print v
    
  6. from https://stackoverflow.com/questions/5434400/python-make-class-iterable by cc-by-sa and MIT license