I am writing a Python wrapper class for a C# API accessed through Pythonnet. As I want to extend the API with my own methods I decided to wrap it using the composition approach outlined here:
The C# API makes heavy use of properties which I want to mimic in my Python code. The following minimal example shows my current approach for the example of the C# Surface class with the two properties width and height:
class MySurface:
def __init__(api_surface):
self.api_surface = api_surface
@property
def width(self):
return self.api_surface.width
@width.setter
def width(self, value):
self.api_surface.width = value
@property
def height(self):
return self.api_surface.height
@height.setter
def height(self, value):
self.api_surface.height = value
In total, I have to deal with about 50 properties. For several groups of properties I want to add my own error checks, type conversions, etc. What I am looking for is a Pythonic way of defining the properties, e.g. through a factory or using descriptors. Thanks for your help!
Edit: I want to be able to use tab completion within a python shell, i.e. surface. {hit tab} should propose surface.width and surface.height. This does not seem to be possible with the getattr approach outlined by Greg.
Normally, Python uses methods like getters and setters to adjust the values on attributes without any special processing. It’s just a basic storage system. Sometimes, You might need to validate the values that are being assigned to a value. A descriptor is a mechanism behind properties, methods, static methods, class methods, and super ().
Let’s understand the syntax, and how its works with an example: In this example, the decorator rebinds the class C to another class Wrapper, which retains the original class in an enclosing scope and creates and embeds an instance (wrap) of the original class when it’s called.
To see how property () is implemented in terms of the descriptor protocol, here is a pure Python equivalent: The property () builtin helps whenever a user interface has granted attribute access and then subsequent changes require the intervention of a method.
This method is used when the same descriptor is needed across many different classes and attributes, for example, for type validation. In this we use the power of property decorators which are a combination of property type method and Python decorators. Writing code in comment?
I was able to solve the issue using the following property factory:
def surface_property(api_property_name, docstring=None):
def getter(self):
return self.api_surface.__getattribute__(api_property_name)
def setter(self, value):
self.api_surface.__setattr__(api_property_name, value)
return property(getter, setter, doc=docstring)
With this function the class definition reduces to:
class MySurface:
def __init__(api_surface):
self.api_surface = api_surface
width = surface_property('Width','Get and set the width.')
height = surface_property('height', 'Get and set the height.')
You can just use getattr and setattr if you want to avoid all the manual coding. This answer will work for python2 btw.
class MySurface(object):
def __init__(self):
self.props = {"width": 0, "length": 0, ...}
def __setattr__(self, attr, val):
if attr in self.props:
self.props[attr] = val
else:
super(MySurface, self).__setattr__(attr, val)
def __getattr__(self, attr):
if attr in self.props:
return self.props[attr]
else:
return self.__getattribute__(attr)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With