복붙노트

[PYTHON] 파이썬에서의 C와 같은 구조

PYTHON

파이썬에서의 C와 같은 구조

Python에서 C와 유사한 구조를 편리하게 정의 할 수있는 방법이 있습니까? 나는 다음과 같이 쓰는 것에 질려합니다.

class MyStruct():
    def __init__(self, field1, field2, field3):
        self.field1 = field1
        self.field2 = field2
        self.field3 = field3

해결법

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

    1.파이썬 2.6에서 표준 라이브러리의 콜렉션 모듈에 추가 된 명명 된 튜플을 사용하십시오. Python 2.4를 지원해야하는 경우 Raymond Hettinger의 튜플 레시피를 사용할 수도 있습니다.

    파이썬 2.6에서 표준 라이브러리의 콜렉션 모듈에 추가 된 명명 된 튜플을 사용하십시오. Python 2.4를 지원해야하는 경우 Raymond Hettinger의 튜플 레시피를 사용할 수도 있습니다.

    기본 예제에는 좋지만 이후에 실행할 수있는 일련의 모서리 사례도 다룹니다. 위의 조각은 다음과 같이 작성됩니다.

    from collections import namedtuple
    MyStruct = namedtuple("MyStruct", "field1 field2 field3")
    

    새로 생성 된 유형은 다음과 같이 사용할 수 있습니다.

    m = MyStruct("foo", "bar", "baz")
    

    명명 된 인수를 사용할 수도 있습니다.

    m = MyStruct(field1="foo", field2="bar", field3="baz")
    
  2. ==============================

    2.튜플은 C에서 구조체를 사용하는 많은 것들 (x, y 좌표 또는 RGB 색상과 같은 것)을 사용할 수 있습니다.

    튜플은 C에서 구조체를 사용하는 많은 것들 (x, y 좌표 또는 RGB 색상과 같은 것)을 사용할 수 있습니다.

    다른 모든 것에 대해서는 사전이나이 유틸리티 클래스를 사용할 수 있습니다 :

    >>> class Bunch:
    ...     def __init__(self, **kwds):
    ...         self.__dict__.update(kwds)
    ...
    >>> mystruct = Bunch(field1=value1, field2=value2)
    

    파이썬 쿡북 (Python Cookbook)의 출판 된 버전에서 "결정적인"논의가 여기에 있다고 생각합니다.

  3. ==============================

    3.아마도 생성자가없는 Structs를 찾고있을 것입니다.

    아마도 생성자가없는 Structs를 찾고있을 것입니다.

    class Sample:
      name = ''
      average = 0.0
      values = None # list cannot be initialized here!
    
    
    s1 = Sample()
    s1.name = "sample 1"
    s1.values = []
    s1.values.append(1)
    s1.values.append(2)
    s1.values.append(3)
    
    s2 = Sample()
    s2.name = "sample 2"
    s2.values = []
    s2.values.append(4)
    
    for v in s1.values:   # prints 1,2,3 --> OK.
      print v
    print "***"
    for v in s2.values:   # prints 4 --> OK.
      print v
    
  4. ==============================

    4.사전은 어때?

    사전은 어때?

    이 같은:

    myStruct = {'field1': 'some val', 'field2': 'some val'}
    

    그런 다음 이것을 사용하여 값을 조작 할 수 있습니다.

    print myStruct['field1']
    myStruct['field2'] = 'some other values'
    

    그리고 그 값은 문자열 일 필요는 없습니다. 그들은 꽤 많은 다른 대상이 될 수 있습니다.

  5. ==============================

    5.파이썬 3.7에서 데이터 클래스가 도입됨에 따라 우리는 매우 가까워졌습니다.

    파이썬 3.7에서 데이터 클래스가 도입됨에 따라 우리는 매우 가까워졌습니다.

    다음 예제는 아래 NamedTuple 예제와 비슷하지만 결과 객체는 변경할 수 있으며 기본값을 허용합니다.

    @dataclass
    class Point:
        x: float
        y: float
        z: float = 0.0
    
    p = Point(1.5, 2.5)
    print(p)   # produces "Point(x=1.5, y=2.5, z=0.0)"
    

    더 구체적인 유형 주석을 사용하려는 경우 새로운 타이핑 모듈과 잘 어울립니다.

    나는 이것을 위해 필사적으로 기다리고 있었다! 네가 나에게 묻는다면, 데이터 클래스와 타이핑 모듈과 결합 된 새로운 NamedTuple 선언은 신의 선물이다!

    파이썬 3.6 이후로 당신은 변함없이 살 수있는 한 아주 간단하고 아름답게되었습니다 (IMHO).

    유형 주석을 허용하는 NamedTuples을 선언하는 새로운 방법이 소개되었습니다.

    from typing import NamedTuple
    
    class MyStruct(NamedTuple):
        my_string: str
        my_int: int
        my_list: list
        my_dict: dict
        my_foo: Foo
    

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

    my_item = MyStruct(
        my_string='foo',
        my_int=0,
        my_list=['bar'],
        my_dict={'baz': 'qux'},
        my_foo=Foo('bar')
    )
    

    또는 정말로 원한다면 다음과 같이하십시오.

    my_item = MyStruct('foo', 0, ['bar'], {'baz': 'qux'}, Foo('bar'))
    
  6. ==============================

    6.클래스의 필드, 메서드 및 모든 속성은 dicts (적어도 CPython에서는)를 사용하여 내부적으로 저장되기 때문에 사전을 사용하여 클래스 필드에 액세스 할 수 있습니다.

    클래스의 필드, 메서드 및 모든 속성은 dicts (적어도 CPython에서는)를 사용하여 내부적으로 저장되기 때문에 사전을 사용하여 클래스 필드에 액세스 할 수 있습니다.

    ... 두 번째 코멘트로 연결됩니다. 파이썬 독트린이 "무겁다"고 믿는 것은 극히 비 파이썬 론적 개념입니다. 그리고 그러한 주석을 읽으면 제 Python Zen이 죽습니다. 그 좋지 않다.

    클래스를 선언 할 때 실제로는 사전 주위에 꽤 복잡한 래퍼를 작성합니다. 따라서 어떤 경우에는 간단한 사전을 사용하는 것보다 오버 헤드를 추가하는 것입니다. 모든 경우에 의미없는 오버 헤드입니다. 성능이 중요한 응용 프로그램에서 작업하는 경우 C 또는 무언가를 사용하십시오.

  7. ==============================

    7.위치 매개 변수로 init 매개 변수를 전달할 수도 있습니다

    위치 매개 변수로 init 매개 변수를 전달할 수도 있습니다

    # Abstract struct class       
    class Struct:
        def __init__ (self, *argv, **argd):
            if len(argd):
                # Update by dictionary
                self.__dict__.update (argd)
            else:
                # Update by position
                attrs = filter (lambda x: x[0:2] != "__", dir(self))
                for n in range(len(argv)):
                    setattr(self, attrs[n], argv[n])
    
    # Specific class
    class Point3dStruct (Struct):
        x = 0
        y = 0
        z = 0
    
    pt1 = Point3dStruct()
    pt1.x = 10
    
    print pt1.x
    print "-"*10
    
    pt2 = Point3dStruct(5, 6)
    
    print pt2.x, pt2.y
    print "-"*10
    
    pt3 = Point3dStruct (x=1, y=2, z=3)
    print pt3.x, pt3.y, pt3.z
    print "-"*10
    
  8. ==============================

    8.표준 라이브러리에서 사용 가능한 C 구조를 서브 클래스화할 수 있습니다. ctypes 모듈은 Structure 클래스를 제공합니다. 문서의 예 :

    표준 라이브러리에서 사용 가능한 C 구조를 서브 클래스화할 수 있습니다. ctypes 모듈은 Structure 클래스를 제공합니다. 문서의 예 :

    >>> from ctypes import *
    >>> class POINT(Structure):
    ...     _fields_ = [("x", c_int),
    ...                 ("y", c_int)]
    ...
    >>> point = POINT(10, 20)
    >>> print point.x, point.y
    10 20
    >>> point = POINT(y=5)
    >>> print point.x, point.y
    0 5
    >>> POINT(1, 2, 3)
    Traceback (most recent call last):
      File "<stdin>", line 1, in ?
    ValueError: too many initializers
    >>>
    >>> class RECT(Structure):
    ...     _fields_ = [("upperleft", POINT),
    ...                 ("lowerright", POINT)]
    ...
    >>> rc = RECT(point)
    >>> print rc.upperleft.x, rc.upperleft.y
    0 5
    >>> print rc.lowerright.x, rc.lowerright.y
    0 0
    >>>
    
  9. ==============================

    9."사전처럼 작동하는 즉석 데이터 객체"가 필요할 때마다 (나는 C 구조체를 생각하지 않습니다!),이 귀여운 해킹을 생각합니다.

    "사전처럼 작동하는 즉석 데이터 객체"가 필요할 때마다 (나는 C 구조체를 생각하지 않습니다!),이 귀여운 해킹을 생각합니다.

    class Map(dict):
        def __init__(self, **kwargs):
            super(Map, self).__init__(**kwargs)
            self.__dict__ = self
    

    이제 다음과 같이 말할 수 있습니다.

    struct = Map(field1='foo', field2='bar', field3=42)
    
    self.assertEquals('bar', struct.field2)
    self.assertEquals(42, struct['field3'])
    

    "클래스가 아닌 데이터 가방"이 필요할 때와 namedtuples이 이해할 수없는 경우를 위해 완벽하게 편리한 시간 ...

  10. ==============================

    10.또한 슬롯을 사용하는 솔루션을 추가하고 싶습니다.

    또한 슬롯을 사용하는 솔루션을 추가하고 싶습니다.

    class Point:
        __slots__ = ["x", "y"]
        def __init__(self, x, y):
            self.x = x
            self.y = y
    

    확실히 슬롯에 대한 문서를 확인하지만 슬롯에 대한 간단한 설명은 파이썬의 말하는 방식입니다. "이 속성들을 클래스에 잠그면 클래스에 일단 새로운 속성을 추가하지 않겠다고 커밋 할 수 있다면 (예를 들어 클래스 인스턴스에 새로운 속성을 추가 할 수 있습니다. 아래 예제 참조) 클래스 인스턴스에 새로운 속성을 추가하고 이러한 슬롯 된 속성에 필요한 것을 사용하도록 허용하는 대용량 메모리 할당을 제거합니다. "

    클래스 인스턴스에 속성을 추가하는 예 (따라서 슬롯을 사용하지 않음) :

    class Point:
        def __init__(self, x, y):
            self.x = x
            self.y = y
    
    p1 = Point(3,5)
    p1.z = 8
    print(p1.z)
    

    출력 : 8

    슬롯이 사용 된 클래스 인스턴스에 속성을 추가하는 예 :

    class Point:
        __slots__ = ["x", "y"]
        def __init__(self, x, y):
            self.x = x
            self.y = y
    
    p1 = Point(3,5)
    p1.z = 8
    

    출력 : AttributeError : 'Point'객체에 'z'속성이 없습니다.

    이것은 효과적으로 구조체로 작동 할 수 있으며 클래스보다 적은 메모리를 사용합니다 (정확히 얼마만큼 연구하지는 않았지만 구조체처럼). 많은 양의 객체 인스턴스를 만들고 속성을 추가 할 필요가없는 경우 슬롯을 사용하는 것이 좋습니다. 점 개체는 데이터 집합을 설명하기 위해 많은 점을 인스턴스화 할 가능성이 있기 때문에 좋은 예입니다.

  11. ==============================

    11.다음과 같은 방법으로 파이썬에서 C-Style 구조체에 액세스합니다.

    다음과 같은 방법으로 파이썬에서 C-Style 구조체에 액세스합니다.

    class cstruct:
        var_i = 0
        var_f = 0.0
        var_str = ""
    
    obj = cstruct()
    obj.var_i = 50
    obj.var_f = 50.00
    obj.var_str = "fifty"
    print "cstruct: obj i=%d f=%f s=%s" %(obj.var_i, obj.var_f, obj.var_str)
    
    obj_array = [cstruct() for i in range(10)]
    obj_array[0].var_i = 10
    obj_array[0].var_f = 10.00
    obj_array[0].var_str = "ten"
    
    #go ahead and fill rest of array instaces of struct
    
    #print all the value
    for i in range(10):
        print "cstruct: obj_array i=%d f=%f s=%s" %(obj_array[i].var_i, obj_array[i].var_f, obj_array[i].var_str)
    

    노트 : 'cstruct'대신에 구조체 이름을 사용하십시오. var_i, var_f, var_str 대신 구조체의 멤버 변수를 정의하십시오.

  12. ==============================

    12.여기에 대한 답은 대단히 정교합니다. 내가 찾은 가장 간단한 옵션은 다음과 같습니다 (http://norvig.com/python-iaq.html).

    여기에 대한 답은 대단히 정교합니다. 내가 찾은 가장 간단한 옵션은 다음과 같습니다 (http://norvig.com/python-iaq.html).

    class Struct:
        "A structure that can have any fields defined."
        def __init__(self, **entries): self.__dict__.update(entries)
    

    초기화 중 :

    >>> options = Struct(answer=42, linelen=80, font='courier')
    >>> options.answer
    42
    

    더 추가 :

    >>> options.cat = "dog"
    >>> options.cat
    dog
    

    편집 : 죄송 합니다이 예제는 이미 더 아래로 보지 못했습니다.

  13. ==============================

    13.어떤 메소드에서나 사용할 수있는 데코레이터를 작성하여 전달 된 모든 인수 또는 기본값이 인스턴스에 지정되도록했습니다.

    어떤 메소드에서나 사용할 수있는 데코레이터를 작성하여 전달 된 모든 인수 또는 기본값이 인스턴스에 지정되도록했습니다.

    def argumentsToAttributes(method):
        argumentNames = method.func_code.co_varnames[1:]
    
        # Generate a dictionary of default values:
        defaultsDict = {}
        defaults = method.func_defaults if method.func_defaults else ()
        for i, default in enumerate(defaults, start = len(argumentNames) - len(defaults)):
            defaultsDict[argumentNames[i]] = default
    
        def newMethod(self, *args, **kwargs):
            # Use the positional arguments.
            for name, value in zip(argumentNames, args):
                setattr(self, name, value)
    
            # Add the key word arguments. If anything is missing, use the default.
            for name in argumentNames[len(args):]:
                setattr(self, name, kwargs.get(name, defaultsDict[name]))
    
            # Run whatever else the method needs to do.
            method(self, *args, **kwargs)
    
        return newMethod
    

    빠른 데모. 위치 인수 a를 사용하고 b의 기본값과 이름 지정된 인수 c를 사용합니다. 그런 다음 메서드가 입력되기 전에 적절하게 할당되었음을 보여주기 위해 3 개의 참조하는 자체를 모두 인쇄합니다.

    class A(object):
        @argumentsToAttributes
        def __init__(self, a, b = 'Invisible', c = 'Hello'):
            print(self.a)
            print(self.b)
            print(self.c)
    
    A('Why', c = 'Nothing')
    

    내 데코레이터는 __init__뿐만 아니라 어떤 방법으로도 작동해야합니다.

  14. ==============================

    14.조금 늦었 겠지만 파이썬 메타 클래스 (아래의 데코레이터 버전)를 사용하여 솔루션을 만들었습니다.

    조금 늦었 겠지만 파이썬 메타 클래스 (아래의 데코레이터 버전)를 사용하여 솔루션을 만들었습니다.

    런타임 중에 __init__을 호출하면 각 인수와 해당 값을 가져 와서 클래스에 인스턴스 변수로 지정합니다. 이렇게하면 모든 값을 수동으로 할당 할 필요없이 구조체와 비슷한 클래스를 만들 수 있습니다.

    내보기에는 오류 검사가 없으므로 따라하기 쉽습니다.

    class MyStruct(type):
        def __call__(cls, *args, **kwargs):
            names = cls.__init__.func_code.co_varnames[1:]
    
            self = type.__call__(cls, *args, **kwargs)
    
            for name, value in zip(names, args):
                setattr(self , name, value)
    
            for name, value in kwargs.iteritems():
                setattr(self , name, value)
            return self 
    

    여기에서 그것은 행동 중입니다.

    >>> class MyClass(object):
        __metaclass__ = MyStruct
        def __init__(self, a, b, c):
            pass
    
    
    >>> my_instance = MyClass(1, 2, 3)
    >>> my_instance.a
    1
    >>> 
    

    나는 reddit에 그것을 게시했고 / u / matchu는 더 깨끗한 데코레이터 버전을 게시했다. 메타 클래스 버전을 확장하고 싶지 않으면 사용하는 것이 좋습니다.

    >>> def init_all_args(fn):
        @wraps(fn)
        def wrapped_init(self, *args, **kwargs):
            names = fn.func_code.co_varnames[1:]
    
            for name, value in zip(names, args):
                setattr(self, name, value)
    
            for name, value in kwargs.iteritems():
                setattr(self, name, value)
    
        return wrapped_init
    
    >>> class Test(object):
        @init_all_args
        def __init__(self, a, b):
            pass
    
    
    >>> a = Test(1, 2)
    >>> a.a
    1
    >>> 
    
  15. ==============================

    15.이 대답은 여기에 표시되지 않으므로 지금 Python을 배우고 발견 한 이후로 추가하겠다. Python 튜토리얼 (이 경우 Python 2)은 다음과 같은 간단하고 효과적인 예제를 제공합니다.

    이 대답은 여기에 표시되지 않으므로 지금 Python을 배우고 발견 한 이후로 추가하겠다. Python 튜토리얼 (이 경우 Python 2)은 다음과 같은 간단하고 효과적인 예제를 제공합니다.

    class Employee:
        pass
    
    john = Employee()  # Create an empty employee record
    
    # Fill the fields of the record
    john.name = 'John Doe'
    john.dept = 'computer lab'
    john.salary = 1000
    

    즉, 빈 클래스 객체가 만들어지고 인스턴스화되며 필드가 동적으로 추가됩니다.

    이것에 대한 측면은 정말 간단합니다. 단점은 특히 자체 문서화가되지 않는다는 것입니다 (의도 된 멤버가 클래스 "정의"의 아무 곳에도 나열되지 않음). 설정하지 않은 필드는 액세스 할 때 문제를 일으킬 수 있습니다. 이 두 가지 문제는 다음과 같이 해결할 수 있습니다.

    class Employee:
        def __init__ (self):
            self.name = None # or whatever
            self.dept = None
            self.salary = None
    

    이제 한눈에 프로그램이 어떤 분야에서 기대되는지 확인할 수 있습니다.

    둘 다 오타가 생기기 쉽고, john.slarly = 1000이 성공합니다. 아직도, 그것은 작동합니다.

  16. ==============================

    16.개인적으로이 변형도 마음에 든다. 그것은 @ dF의 대답을 확장합니다.

    개인적으로이 변형도 마음에 든다. 그것은 @ dF의 대답을 확장합니다.

    class struct:
        def __init__(self, *sequential, **named):
            fields = dict(zip(sequential, [None]*len(sequential)), **named)
            self.__dict__.update(fields)
        def __repr__(self):
            return str(self.__dict__)
    

    이것은 두 가지 초기화 모드를 지원합니다 (혼합 가능).

    # Struct with field1, field2, field3 that are initialized to None.
    mystruct1 = struct("field1", "field2", "field3") 
    # Struct with field1, field2, field3 that are initialized according to arguments.
    mystruct2 = struct(field1=1, field2=2, field3=3)
    

    또한 더 멋지게 인쇄합니다.

    print(mystruct2)
    # Prints: {'field3': 3, 'field1': 1, 'field2': 2}
    
  17. ==============================

    17.struct에 대한 다음 솔루션은 namedtuple 구현과 이전 답변에서 영감을 얻은 것입니다. 그러나 namedtuple과는 달리 값은 가변적이지만 이름이나 속성에는 변경할 수없는 c 스타일의 struct와 비슷합니다. 일반 클래스 나 dict는 그렇지 않습니다.

    struct에 대한 다음 솔루션은 namedtuple 구현과 이전 답변에서 영감을 얻은 것입니다. 그러나 namedtuple과는 달리 값은 가변적이지만 이름이나 속성에는 변경할 수없는 c 스타일의 struct와 비슷합니다. 일반 클래스 나 dict는 그렇지 않습니다.

    _class_template = """\
    class {typename}:
    def __init__(self, *args, **kwargs):
        fields = {field_names!r}
    
        for x in fields:
            setattr(self, x, None)            
    
        for name, value in zip(fields, args):
            setattr(self, name, value)
    
        for name, value in kwargs.items():
            setattr(self, name, value)            
    
    def __repr__(self):
        return str(vars(self))
    
    def __setattr__(self, name, value):
        if name not in {field_names!r}:
            raise KeyError("invalid name: %s" % name)
        object.__setattr__(self, name, value)            
    """
    
    def struct(typename, field_names):
    
        class_definition = _class_template.format(
            typename = typename,
            field_names = field_names)
    
        namespace = dict(__name__='struct_%s' % typename)
        exec(class_definition, namespace)
        result = namespace[typename]
        result._source = class_definition
    
        return result
    

    용법:

    Person = struct('Person', ['firstname','lastname'])
    generic = Person()
    michael = Person('Michael')
    jones = Person(lastname = 'Jones')
    
    
    In [168]: michael.middlename = 'ben'
    Traceback (most recent call last):
    
      File "<ipython-input-168-b31c393c0d67>", line 1, in <module>
    michael.middlename = 'ben'
    
      File "<string>", line 19, in __setattr__
    
    KeyError: 'invalid name: middlename'
    
  18. ==============================

    18.파이썬 구조체 사전이이 요구 사항에 적합하다고 생각합니다.

    파이썬 구조체 사전이이 요구 사항에 적합하다고 생각합니다.

    d = dict{}
    d[field1] = field1
    d[field2] = field2
    d[field2] = field3
    
  19. ==============================

    19.https://stackoverflow.com/a/32448434/159695는 Python3에서 작동하지 않습니다.

    https://stackoverflow.com/a/32448434/159695는 Python3에서 작동하지 않습니다.

    https://stackoverflow.com/a/35993/159695는 Python3에서 작동합니다.

    기본 값을 추가하기 위해 그것을 확장합니다.

    class myStruct:
        def __init__(self, **kwds):
            self.x=0
            self.__dict__.update(kwds) # Must be last to accept assigned member variable.
        def __repr__(self):
            args = ['%s=%s' % (k, repr(v)) for (k,v) in vars(self).items()]
            return '%s(%s)' % ( self.__class__.__qualname__, ', '.join(args) )
    
    a=myStruct()
    b=myStruct(x=3,y='test')
    c=myStruct(x='str')
    
    >>> a
    myStruct(x=0)
    >>> b
    myStruct(x=3, y='test')
    >>> c
    myStruct(x='str')
    
  20. from https://stackoverflow.com/questions/35988/c-like-structures-in-python by cc-by-sa and MIT license