470,596 Members | 1,564 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 470,596 developers. It's quick & easy.

succint representation of struct arguments

I want to import some binary data with the struct module, edit it, then export it again. The problem is that I can't find a shorthand way to represent my list of data without having to write it twice. The simple way to do this is:
Expand|Select|Wrap|Line Numbers
  1. [mass,speed,width] = struct.unpack("BBB", "\x01\x02\x03")
  2. mass+=1
  3. struct.pack("BBB", mass, speed, width)
  4.  
The problem is that I have to write my variables twice, which poses problems for maintenence (my real program has many more elements). The ideal solution would be one that only requires me to write out my elements once. With the C preprocessor I could something like this:
Expand|Select|Wrap|Line Numbers
  1. #define args mass,speed,width
  2. [args] = struct.unpack("BBB", "\x01\x02\x03")
  3. mass += 1
  4. struct.pack("BBB", args)
  5.  
Of course, python doesn't have a text preprocessor. Doing things the python way, the major obstacles are:
1) Deal with the variable argument list. I can do that with struct.unpack("BBB", *args)
2) Pass my elements by reference. This is where I'm stuck. If mass, speed, and width were objects, then I could pass them by reference as in the first example and all would be fine. But they can't be objects; they must be ints. The best syntax I can come up with is
Expand|Select|Wrap|Line Numbers
  1. format = {'mass':0,'speed':1,'width':2}
  2. foo = list(struct.unpack("BBB", "\x01\x02\x03"))
  3. foo[format['mass']] += 1
  4. struct.pack("BBB", *foo)
  5.  
But the dictionary references are ugly and unintuitive. Is there a more natural way to do this in python?

In fact, I'm still representing my list twice, because I define its members in one place (format) and its layout in another "BBB". An even better solution would combine those, but I don't see how.
May 3 '07 #1
5 2002
bvdet
2,851 Expert Mod 2GB
I want to import some binary data with the struct module, edit it, then export it again. The problem is that I can't find a shorthand way to represent my list of data without having to write it twice. The simple way to do this is:
Expand|Select|Wrap|Line Numbers
  1. [mass,speed,width] = struct.unpack("BBB", "\x01\x02\x03")
  2. mass+=1
  3. struct.pack("BBB", mass, speed, width)
  4.  
The problem is that I have to write my variables twice, which poses problems for maintenence (my real program has many more elements). The ideal solution would be one that only requires me to write out my elements once. With the C preprocessor I could something like this:
Expand|Select|Wrap|Line Numbers
  1. #define args mass,speed,width
  2. [args] = struct.unpack("BBB", "\x01\x02\x03")
  3. mass += 1
  4. struct.pack("BBB", args)
  5.  
Of course, python doesn't have a text preprocessor. Doing things the python way, the major obstacles are:
1) Deal with the variable argument list. I can do that with struct.unpack("BBB", *args)
2) Pass my elements by reference. This is where I'm stuck. If mass, speed, and width were objects, then I could pass them by reference as in the first example and all would be fine. But they can't be objects; they must be ints. The best syntax I can come up with is
Expand|Select|Wrap|Line Numbers
  1. format = {'mass':0,'speed':1,'width':2}
  2. foo = list(struct.unpack("BBB", "\x01\x02\x03"))
  3. foo[format['mass']] += 1
  4. struct.pack("BBB", *foo)
  5.  
But the dictionary references are ugly and unintuitive. Is there a more natural way to do this in python?

In fact, I'm still representing my list twice, because I define its members in one place (format) and its layout in another "BBB". An even better solution would combine those, but I don't see how.
Is this any better?
Expand|Select|Wrap|Line Numbers
  1. varList = 'mass','speed','width'
  2. dd = dict(zip(varList, struct.unpack("BBB", "\x01\x02\x03")))
  3. dd['mass']+= 1
  4. struct.pack("BBB", *[dd[key] for key in varList])
May 3 '07 #2
Is this any better?
Expand|Select|Wrap|Line Numbers
  1. varList = 'mass','speed','width'
  2. dd = dict(zip(varList, struct.unpack("BBB", "\x01\x02\x03")))
  3. dd['mass']+= 1
  4. struct.pack("BBB", *[dd[key] for key in varList])
That is better. I never thought to use a dictionary like that. There is still dd though. Is there any way to copy simple types by reference, something like
Expand|Select|Wrap|Line Numbers
  1. a=5
  2. b=ref(a)
  3. b+=1
  4. a==6
  5.  
May 3 '07 #3
I think I've found the best solution now. I'm still using dd as suggested by bvdet, along with another new trick to clean up the syntax. This is all happening within a class, of course, so I can overload __getattr__ to hide dd from the user of the class. I just write
Expand|Select|Wrap|Line Numbers
  1. def __getattr__(self, name):
  2.     try:
  3.         return self.dd[name]
  4.     except KeyError:
  5.         raise AttributeError
  6.  
within the class, and then programs can refer to the struct arguments as if they were class attributes, e.g. myclass.mass instead of myclass.dd['mass']. This is my final solution.
May 21 '07 #4
bartonc
6,596 Expert 4TB
I think I've found the best solution now. I'm still using dd as suggested by bvdet, along with another new trick to clean up the syntax. This is all happening within a class, of course, so I can overload __getattr__ to hide dd from the user of the class. I just write
Expand|Select|Wrap|Line Numbers
  1. def __getattr__(self, name):
  2.     try:
  3.         return self.dd[name]
  4.     except KeyError:
  5.         raise AttributeError
  6.  
within the class, and then programs can refer to the struct arguments as if they were class attributes, e.g. myclass.mass instead of myclass.dd['mass']. This is my final solution.
Very Pythonic! Thanks for the update to you very elegant solution.
May 21 '07 #5
bvdet
2,851 Expert Mod 2GB
I think I've found the best solution now. I'm still using dd as suggested by bvdet, along with another new trick to clean up the syntax. This is all happening within a class, of course, so I can overload __getattr__ to hide dd from the user of the class. I just write
Expand|Select|Wrap|Line Numbers
  1. def __getattr__(self, name):
  2.     try:
  3.         return self.dd[name]
  4.     except KeyError:
  5.         raise AttributeError
  6.  
within the class, and then programs can refer to the struct arguments as if they were class attributes, e.g. myclass.mass instead of myclass.dd['mass']. This is my final solution.
Thank you for sharing your solution with us.
May 21 '07 #6

Post your reply

Sign in to post your reply or Sign up for a free account.

Similar topics

reply views Thread by Josiah Carlson | last post: by
9 posts views Thread by Arun Goel | last post: by
10 posts views Thread by 63q2o4i02 | last post: by
6 posts views Thread by godavemon | last post: by
9 posts views Thread by johan.tibell | last post: by
10 posts views Thread by Richard Tobin | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.