little libreria example endian ejemplos data python struct

python - libreria - struct module



Estructuras tipo C en Python (19)

dF: eso es muy bueno ... No sabía que podía acceder a los campos en una clase usando dict.

Mark: las situaciones en las que desearía tener esto son precisamente cuando quiero una tupla pero nada tan "pesado" como un diccionario.

Puede acceder a los campos de una clase utilizando un diccionario porque los campos de una clase, sus métodos y todas sus propiedades se almacenan internamente utilizando dictados (al menos en CPython).

... Lo que nos lleva a tu segundo comentario. Creer que los dictados de Python son "pesados" es un concepto extremadamente no pitón. Y leer esos comentarios mata a mi Python Zen. Eso no es bueno.

Usted ve, cuando declara una clase, en realidad está creando una envoltura bastante compleja alrededor de un diccionario, por lo que, en todo caso, está agregando más sobrecarga que utilizando un diccionario simple. Una sobrecarga que, por cierto, no tiene sentido en ningún caso. Si está trabajando en aplicaciones de rendimiento crítico, use C o algo así.

¿Hay alguna manera de definir convenientemente una estructura tipo C en Python? Estoy cansado de escribir cosas como:

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


Actualización : Clases de datos

Con la introducción de las clases de datos en Python 3.7 nos acercamos mucho.

El siguiente ejemplo es similar al ejemplo de NamedTuple a continuación, pero el objeto resultante es mutable y permite valores predeterminados.

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)

Esto funciona bien con el nuevo módulo de typing en caso de que desee utilizar anotaciones de tipo más específicas.

¡He estado esperando desesperadamente esto! ¡Si me preguntas, las Clases de datos y la nueva declaración NamedTuple , combinadas con el módulo de mecanografía , son una bendición!

Declaración de NamedTuple mejorada

Desde Python 3.6 se volvió bastante simple y hermoso (IMHO), siempre y cuando puedas vivir con inmutabilidad .

Se introdujo una nueva forma de declarar NamedTuples, que también permite typing :

from typing import NamedTuple 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''))


¿Qué tal un diccionario?

Algo como esto:

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

Entonces puedes usar esto para manipular valores:

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

Y los valores no tienen que ser cadenas. Pueden ser prácticamente cualquier otro objeto.


Algunas de las respuestas aquí son masivamente elaboradas. La opción más sencilla que he encontrado es (de: http://norvig.com/python-iaq.html ):

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

Inicializando:

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

añadiendo más:

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

Edición: Lo siento, no vi este ejemplo ya más abajo.


Creo que el diccionario de estructura de Python es adecuado para este requisito.

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


Escribí un decorador que puedes usar en cualquier método para que todos los argumentos pasados, o cualquier defecto, sean asignados a la instancia.

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

Una demostración rápida. Tenga en cuenta que uso un argumento posicional a , uso el valor predeterminado para b y un argumento con nombre c . A continuación, imprimo las 3 referencias del self , para mostrar que se asignaron correctamente antes de ingresar el método.

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

Tenga en cuenta que mi decorador debería trabajar con cualquier método, no solo __init__ .


Esto puede ser un poco tarde, pero hice una solución usando Python Meta-Classes (la versión de decorador a continuación también).

Cuando se llama a __init__ durante el tiempo de ejecución, toma cada uno de los argumentos y su valor y los asigna como variables de instancia a su clase. De esta manera, puede hacer una clase de estructura sin tener que asignar cada valor manualmente.

Mi ejemplo no tiene comprobación de errores por lo que es más fácil de seguir.

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

Aquí está en acción.

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

Lo /u/matchu en reddit y /u/matchu una versión /u/matchu que es más limpia. Le recomiendo que lo use a menos que desee expandir la versión de metaclase.

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


La siguiente solución para una estructura está inspirada en la implementación de namedtuple y algunas de las respuestas anteriores. Sin embargo, a diferencia del timbre nombrado es mutable, en sus valores, pero como la estructura de estilo C inmutable en los nombres / atributos, que no es una clase normal o 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

Uso:

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


No veo esta respuesta aquí, así que me imagino que la agregaré ya que me estoy inclinando sobre Python en este momento y lo acabo de descubrir. El tutorial de Python (Python 2 en este caso) ofrece el siguiente ejemplo simple y efectivo:

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

Es decir, se crea un objeto de clase vacío, se crea una instancia y los campos se agregan dinámicamente.

El lado positivo de esto es su muy simple. La desventaja es que no es particularmente autodocumentada (los miembros previstos no aparecen en ninguna parte de la "definición" de la clase), y los campos sin establecer pueden causar problemas cuando se accede a ellos. Esos dos problemas se pueden resolver mediante:

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

Ahora, de un vistazo, al menos puede ver qué campos esperará el programa.

Ambos son propensos a errores tipográficos, john.slarly = 1000 tendrá éxito. Aún así, funciona.


Personalmente, me gusta esta variante también. Se extiende la respuesta de @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__)

Admite dos modos de inicialización (que se pueden combinar):

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

Además, se imprime mejor:

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


Puede crear una subclase de la estructura C que está disponible en la biblioteca estándar. El módulo ctypes proporciona una clase de estructura . El ejemplo de la documentación:

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


Puede usar una tupla para muchas cosas en las que usaría una estructura en C (por ejemplo, coordenadas x, y o colores RGB).

Para todo lo demás, puede usar el diccionario, o una clase de utilidad como esta :

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

Creo que la discusión "definitiva" está here , en la versión publicada del Libro de cocina de Python.


Quizás estés buscando Estructuras sin constructores:

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


Se accede a la estructura de estilo C en python de la siguiente manera.

class cstruct: var_i = 0 var_f = 0.0 var_str = ""

Si solo quieres usar objeto de cstruct.

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)

Si quieres crear una matriz de objetos de cstruct.

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)

Nota: en lugar del nombre ''cstruct'', use el nombre de su estructura en lugar de var_i, var_f, var_str, por favor defina la variable miembro de su estructura.


Siempre que necesito un "objeto de datos instantáneos que también se comporta como un diccionario" (¡ no pienso en C structs!), Pienso en este lindo truco:

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

Ahora solo puedes decir:

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

Perfectamente útil para esos momentos en que necesita una "bolsa de datos que NO es una clase", y para cuando las frases nombradas son incomprensibles ...


También me gustaría agregar una solución que use slots :

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

Definitivamente, compruebe la documentación de las ranuras, pero una explicación rápida de las ranuras es que es la manera de Python de decir: "Si puede bloquear estos atributos y solo estos atributos en la clase, de modo que se comprometa a no agregar ningún atributo nuevo una vez que la clase se crea una instancia (sí, puede agregar nuevos atributos a una instancia de clase, vea el ejemplo a continuación) y eliminaré la asignación de memoria grande que permite agregar nuevos atributos a una instancia de clase y usaré solo lo que necesito para estos atributos ".

Ejemplo de agregar atributos a la instancia de clase (por lo tanto, no se utilizan ranuras):

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

Salida: 8

Ejemplo de intentar agregar atributos a la instancia de clase donde se usaron las ranuras:

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

Salida: AttributeError: el objeto ''Point'' no tiene atributo ''z''

Esto puede funcionar efectivamente como una estructura y usa menos memoria que una clase (como lo haría una estructura, aunque no he investigado exactamente cuánto). Se recomienda usar ranuras si va a crear una gran cantidad de instancias del objeto y no necesita agregar atributos. Un objeto puntual es un buen ejemplo de esto, ya que es probable que uno pueda instanciar muchos puntos para describir un conjunto de datos.


También puede pasar los parámetros de inicio a las variables de instancia por posición

# 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


Use una tupla con nombre , que se agregó al módulo de colecciones en la biblioteca estándar en Python 2.6. También es posible utilizar la receta de tuplas nombrada de Raymond Hettinger si necesita ser compatible con Python 2.4.

Es bueno para su ejemplo básico, pero también cubre un montón de casos de borde que puede encontrar más tarde también. Tu fragmento de arriba se escribiría como:

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

El tipo recién creado se puede utilizar así:

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

También puedes usar argumentos con nombre:

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


https://.com/a/32448434/159695 no funciona en Python3.

https://.com/a/35993/159695 funciona en Python3.

Y lo amplío para agregar valores por defecto.

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