Automatically convert from getter / setter to properties

I have a large library written in C ++, and someone created an interface to use it in python (2.6) automatically. Now I have many classes with getter and setter methods. Really: I hate them.

I want to reimplement classes with a more pythonic interface using properties. The problem is that each class has hundreds of getters and setters, and I have many classes. How can I automatically create properties?

For example, if I have a class with the name of MyClassthe methods GetX()and SetX(x), GetY, SetYand so on, how can I automatically create a derived class MyPythonicClasswith the property X(ie, if there is a getter and is writable, if there is a setter), etc.? I would like the mechanism to let me skip some getter / setter pairs where it is better to do the work manually.

+3
source share
4 answers

You can do it here with the class decorator.

def make_properties(c):
    from collections import defaultdict
    props=defaultdict(dict)
    for k,v in vars(c).items():
        if k.startswith("Get"):
            props[k[3:]]['getter']=v
        if k.startswith("Set"):
            props[k[3:]]['setter']=v
    for k,v in props.items():
        setattr(c,k,property(v.get('getter'),v.get('setter')))
    return c

@make_properties
class C(object):
    def GetX(self):
        print "GetX"
        return self._x

    def SetX(self, value):
        print "SetX"
        self._x = value

c=C()
c.X=5
c.X

Here is a slightly more complicated version that allows you to specify a list of items to skip

def make_properties(skip=None):
    if skip is None:
        skip=[]
    def f(c):
        from collections import defaultdict
        props=defaultdict(dict)
        for k,v in vars(c).items():
            if k.startswith("Get"):
                props[k[3:]]['getter']=v
            if k.startswith("Set"):
                props[k[3:]]['setter']=v
        for k,v in props.items():
            if k in skip:
                continue
            setattr(c,k,property(v.get('getter'),v.get('setter')))
        return c
    return f

@make_properties(skip=['Y'])
class C(object):
    def GetX(self):
        print "GetX"
        return self._x

    def SetX(self, value):
        print "SetX"
        self._x = value

    def GetY(self):
        print "GetY"
        return self._y

    def SetY(self, value):
        print "SetY"
        self._y = value

c=C()
c.X=5
c.X
c.Y=5
c.Y
+7
source

metaclass, , Get* Set*, . , , , . . .

+2

, , . ,

  • , . - , , ,
  • ++. , , .

Think about whether it makes sense to deal with the library that you use when it comes to you.

+1
source
class BaseObj:
    test = None
    def __init__(self, attributes_dict):
        self.attributes_dict = attributes_dict
        self.define_getters(attributes_dict.keys())
    def define_getters(self, attributes_names):
        for attribute_name in attributes_names:
            setattr(self, "get_"+attribute_name, self.getter_factory(attribute_name))
    def getter_factory(self, attribute_name):
        """Method for generating getter functions"""
        def getter():
            return self.attributes_dict[attribute_name]
        return getter

class DerivedObj(BaseObj):
    attributes_keys = ['name']
    def __init__(self, attributes_dict):
        BaseObj.__init__(self, attributes_dict)

a = DerivedObj({'name':'kuku'})
a.get_name()  # -> kuku
+1
source

Source: https://habr.com/ru/post/1733083/


All Articles