1

I have a class, that is used to translate binary stream to human readable. I want to translate it both ways, because I send and receive binary messages. Attributes of this class are made mostly the same way - take the bytes from startbyte to stopbyte and decode them - so I made a decision to use a property to do that. But can I make a general "property" that will be used when defining my class attributes?

class Packet(object):
    def __init__(self, data):
        self.data = data

    def standard_getter(startbyte, stopbyte):
        def getter(self):
            return decode(self.data[startbyte:stopbyte])
        return getter

    def standard_setter(startbyte, stopbyte):
        def setter(self, value):
            self.data[startbyte:stopbyte] = encode(value)
    return setter

    # the way I define properties by now:
    protocol_type = property(standard_getter(16, 18), standard_setter(16, 18))
    protocol_sub_type = property(standard_getter(18, 20), standard_setter(18, 20))

    # the way I would like to do it:
    protocol_type = property(standard_property(16, 18))
    # or
    protocol_type = standard_property(16, 18)

I tried to define a function, that takes two arguments and returns property(getter, setter), but always I'm stuck in giving "self" instance to the function. Is there a nice way I can make it?

1 Answer 1

3

Have your function produce both the getter and setter, and return the property object for those two functions:

def standard_property(startbyte, stopbyte):
    def getter(self):
        return decode(self.data[startbyte:stopbyte])
    def setter(self, value):
        self.data[startbyte:stopbyte] = encode(value)
    return property(getter, setter)

Then use the return value directly:

protocol_type = standard_property(16, 18)
protocol_sub_type = standard_property(18, 20)

Note that the standard_property() function doesn't even need to live in your class; it could be a top-level function too:

>>> def standard_property(startbyte, stopbyte):
...     def getter(self):
...         return decode(self.data[startbyte:stopbyte])
...     def setter(self, value):
...         self.data[startbyte:stopbyte] = encode(value)
...     return property(getter, setter)
...
>>> encode = lambda v: list(v)
>>> decode = lambda v: ''.join(v)
>>> class Packet(object):
...     def __init__(self, data):
...         self.data = data
...     protocol_type = standard_property(16, 18)
...     protocol_sub_type = standard_property(18, 20)
...
>>> p = Packet(list('foo bar baz spam ham eggs'))
>>> p.protocol_type
' h'
>>> p.protocol_sub_type
'am'
>>> p.protocol_type = '_c'
>>> p.protocol_sub_type = 'an'
>>> ''.join(p.data)
'foo bar baz spam_can eggs'
Sign up to request clarification or add additional context in comments.

1 Comment

Great one, that's what I needed. I know I can put it outside the class, but by now it makes no sense for me.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.