Page 1 of 1
Extend System Module By Subclassing
Posted: Sun Apr 14, 2019 11:45 pm
by devnull
I realise that this is more of a generic python question rather than micropython specific, but how do I subclass and then add new methods ?
Is it possible to add new methods as well as replace existing ones:
Code: Select all
from network import WLAN
class wlan(WLAN):
def __init__(self):
super().__init__()
def scan(self):
print('replace original scanning method')
super().scan()
def xscan(self):
print('new scan method using sub method')
super().scan()
wlan().xscan()
wlan().scan()
Re: Extend a Module By Subclassing
Posted: Mon Apr 15, 2019 5:51 am
by kevinkk525
Theoretically it is but I'd be very careful. The built-in c classes often don't like being subclassed and are not working as expected. An example might be machine.Pin which doesn't conform to a typical python class and makes subclassing kind of impossible.
Re: Extend a Module By Subclassing
Posted: Mon Apr 15, 2019 9:48 am
by pythoncoder
Yes. There is no problem subclassing a class you have created and, in the subclass, adding new methods. But as Kevin says, subclassing built-in types like
int,
dict or
WLAN is not supported by MicroPython - see
this doc.
Only subclass a built-in type if it has specifically been designed for this purpose. The only example of which I'm aware is
framebuf.
Re: Extend a Module By Subclassing
Posted: Tue Apr 16, 2019 1:33 pm
by tuupola
You could use composition instead of inheritance. Personally I always prefer composition.
Code: Select all
class wlan:
def __init__(self, station):
self._station = station
def scan(self):
print('replace original scanning method')
return self._station.scan()
def xscan(self):
print('new scan method using sub method')
return self._station.scan()
Which you could then use with something like:
Code: Select all
from network import WLAN, STA_IF
original = WLAN(STA_IF)
custom = wlan(original)
custom.xscan()
custom.scan()
Re: Extend a Module By Subclassing
Posted: Tue Apr 16, 2019 11:34 pm
by devnull
Hmm. interesting was not aware of the composition approach, but I guess that custom() will not contain all of the original methods and variables from WLAN() in your example, and that I would need to redefine / link them all if required ?
i.e.
Code: Select all
class wlan:
def __init__(self, station):
self._station = station
self.config = station.config
self.connect = station.connect
self.isconnected = station.isconnected
def scan(self):
print('replace original scanning method')
return self._station.scan()
def xscan(self):
print('new scan method using sub method')
return self._station.scan()
Re: Extend System Module By Subclassing
Posted: Wed Apr 17, 2019 5:11 am
by pythoncoder
Yes, that is the reason why you might prefer inheritance over composition (if it were available). An example is the framebuf class which does allow inheritance. If you write a driver for specific display hardware such that it subclasses framebuf you get a set of fast C graphics primitives; all for zero programming effort and without runtime overhead.
Re: Extend a Module By Subclassing
Posted: Wed Apr 17, 2019 7:57 am
by tuupola
devnull wrote: ↑Tue Apr 16, 2019 11:34 pm
Hmm. interesting was not aware of the composition approach, but I guess that custom() will not contain all of the original methods and variables from WLAN() in your example, and that I would need to redefine / link them all if required ?
You can use
__getattr__ magic. It should work for both attributes and function.
Code: Select all
class wlan:
def __init__(self, station):
self._station = station
def __getattr__(self, name):
return getattr(self._station, name)
def scan(self):
print('replace original scanning method')
return self._station.scan()
def xscan(self):
print('new scan method using sub method')
return self._station.scan()
Re: Extend System Module By Subclassing
Posted: Wed Apr 17, 2019 10:10 am
by devnull
That's very neat, but this does not appear to work:
Code: Select all
from network import WLAN, STA_IF
original = WLAN(STA_IF)
custom = wlan(original)
custom.xscan()
custom.scan()
I have to call:
Re: Extend System Module By Subclassing
Posted: Wed Apr 17, 2019 1:38 pm
by tuupola
Tested with real device and works for me with ESP32. Note that
__getattr__ is called only when accessing an undefined attribute. Here is a bit cleaned up code:
Code: Select all
import network
class wlan:
def __init__(self, mode):
self._station = network.WLAN(mode)
self._station.active(True)
def __getattr__(self, name):
return getattr(self._station, name)
Tested from REPL:
Code: Select all
MicroPython ESP32_LoBo_v3.2.24 - 2018-09-06 on ESP32 board with ESP32
Type "help()" for more information.
>>> import network
>>> from wlan import wlan
>>>
>>> wifi = wlan(network.STA_IF)
>>> wifi.scan
<bound_method>
>>> wifi.scan()
[(b'Manny-3BB', b'd\x12l\x00\xf1\xf0', 1, -79, 4, 'WPA_WPA2_PSK', False), (b'Myroom119819', b'\x04OLc7H', 8, -79, 4, 'WPA_WPA2_PSK', False), (b'Fcape1', b'\x03\x17\xd6\xf5s=', 6, -82, 0, 'OPEN', False),... rest removed]