Question

For the sake of discussion, lets say I want to write and read values from a dictionary but I want to append some string to the dictionary key. Instead of having the user do the string manipulation, I want to hide it inside setter and getter methods. This works no problem with the Python setter method since I can send a list full of information that can be parsed. It does NOT, however, work with the getter method since arguments cannot be sent to getter. I have concocted the workaround shown below where the getter returns a function which accepts the arguments and does what I want. I'm just wondering if this acceptable Python or if I will regret using this approach.

class tester(object):
    def __init__(self):
        self._dict = {}

    def _set(self,some_list):
        self._dict.update({some_list[0]+'_'+some_list[1]: some_list[2]})

    def _get(self):
        return self._func

    def _func(self,key1,key2):
        keys = key1+'_'+key2
        return self._dict[keys]

    props = property(_get, _set)

a = tester()
value = [1,2,3,4,5]
a.props = ('main_key','sub_key',value)
print(a.props('main_key','sub_key'))

I have searched high and low for ways to use setter and getter that suit my needs, but all I see are people asserting that Python doesn't need them and we should all just be adults and access the attributes directly. The closest I've found is this question, but I find my solution more direct.

Was it helpful?

Solution

properties (or any other descriptor) are for computed attributes, that is members that have the semantic of an attribute but needs some computation either on set and/or get. By 'semantic of an attribute', I mean it makes sense, from the client's code, to write:

something = obj.attribute

and / or

obj.attribute = something_else

As soon as you have to pass arguments to a getter or more than one argument to the setter, it doesn't have an attribute semantic, obviously, so you cannot use a computed attribute. The solution is simple: use an explicit getter/setter pair.

The point about getters/setters not being needed in Python is that for anything that has attribute's semantic (but not anything else) you can always turn a direct attribute access to a computed one if and when you need it without breaking the client code. That's not your case here obviously.

tl;dr: abusing properties the way you do is not pythonic and you'd be better with explicit getter and setter.

OTHER TIPS

Here is an example of what you could do using __getitem__ and __setitem__:

class tester(object):

    class Subelement(object):
        def __init__(self, obj, key):
            self.obj = obj
            self.key = key

        def __getitem__(self, subkey):
            return self.obj._dict[self.key + '_' + subkey]

        def __setitem__(self, subkey, value):
            self.obj._dict[self.key + '_' + subkey] = value

    def __init__(self):
        self._dict = {}

    def __getitem__(self, key):
        return Subelement(self, key)
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top