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

파이썬에서 C와 유사한 구조를 편리하게 정의하는 방법이 있습니까? 나는 다음과 같은 것들을 쓰는 데 지쳤다.

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



답변

Python 2.6의 표준 라이브러리에서 collections 모듈 에 추가 된 named tuple을 사용하십시오 . 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")


답변

업데이트 : 데이터 클래스

의 도입으로 데이터 클래스파이썬 3.7 우리는 매우 가까이.

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

from dataclasses import dataclass


@dataclass
class Point:
    x: float
    y: float
    z: float = 0.0


p = Point(1.5, 2.5)

print(p)  # Point(x=1.5, y=2.5, z=0.0)

보다 구체적인 유형 주석을 사용하려는 경우 새로운 타이핑 모듈에서 잘 작동합니다 .

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

향상된 NamedTuple 선언

파이썬 3.6 부터는 불변성으로 살 수있는 한 꽤 간단하고 아름답습니다 (IMHO) .

NamedTuples을 선언 하는 새로운 방법 이 도입되어 유형 주석 도 가능합니다.

from typing import NamedTuple


class User(NamedTuple):
    name: str


class MyStruct(NamedTuple):
    foo: str
    bar: int
    baz: list
    qux: User


my_item = MyStruct('foo', 0, ['baz'], User('peter'))

print(my_item) # MyStruct(foo='foo', bar=0, baz=['baz'], qux=User(name='peter'))


답변

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

다른 모든를 들어 사전, 또는 같은 유틸리티 클래스를 사용할 수있는 이 일을 :

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

필자 는 Python Cookbook의 출판 된 버전에서 “결정적인”토론이 여기 있다고 생각합니다 .


답변

아마도 생성자가없는 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


답변

사전은 어때요?

이 같은:

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

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

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

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


답변

dF : 정말 멋지다 … dict를 사용하여 클래스의 필드에 액세스 할 수 있다는 것을 몰랐다.

Mark : 제가 원했던 상황은 정확히 터플을 원할 때지만 사전처럼 “무거운”것은 아닙니다.

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

… 두 번째 의견으로 우리를 안내합니다. 파이썬 딕트가 “무거운 것”이라고 믿는 것은 비 파이썬 적 개념입니다. 그리고 그러한 주석을 읽으면 Python Zen이 죽습니다. 그 좋지 않다.

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


답변

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

>>> 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
>>>