kopia lustrzana https://github.com/peterhinch/micropython-samples
README improvements.
rodzic
61d312be15
commit
2399918b38
10
README.md
10
README.md
|
@ -227,12 +227,10 @@ may readily be added as required.
|
||||||
Two simple class decorators for objects useful in hardware interfacing.
|
Two simple class decorators for objects useful in hardware interfacing.
|
||||||
Documented [here](./functor_singleton/README.md).
|
Documented [here](./functor_singleton/README.md).
|
||||||
|
|
||||||
Singletons denote classes for which only a single instance will ever occur.
|
Singletons denote classes for which only a single instance can ever occur.
|
||||||
They are contentious in some circles, on the grounds that the single instance
|
They can be useful for hardware interface classes. Their use avoids the need
|
||||||
guarantee may be violated in a specification change. They can be useful in
|
for a global instance: the sole instance may be retrieved efficiently from
|
||||||
hardware contexts where a chip design is unlikely suddenly to change.
|
anywhere in the code.
|
||||||
Singletons denoting hardware interfaces avoid globals and the need to pass
|
|
||||||
references around.
|
|
||||||
|
|
||||||
A functor is a class which is accessed via function call syntax. There is only
|
A functor is a class which is accessed via function call syntax. There is only
|
||||||
one instance, like a singleton. Initial access calls the constructor, with
|
one instance, like a singleton. Initial access calls the constructor, with
|
||||||
|
|
|
@ -1,14 +1,23 @@
|
||||||
|
# Singletons and Functors
|
||||||
|
|
||||||
|
These closely related concepts describe classes which support only a single
|
||||||
|
instance. They share a common purpose of avoiding the need for global data by
|
||||||
|
providing a callable capable of retaining state and whose scope may be that of
|
||||||
|
the module.
|
||||||
|
|
||||||
|
In both cases implementation is via very similar class decorators.
|
||||||
|
|
||||||
# Singleton class decorator
|
# Singleton class decorator
|
||||||
|
|
||||||
A singleton is a class which has only one instance. IT gurus debate whether
|
A singleton is a class with only one instance. Some IT gurus argue against them
|
||||||
they should be used, mainly on the grounds that project aims can change: a need
|
on the grounds that project aims can change: a need for multiple instances may
|
||||||
for multiple instances may arise later. I would argue that singleton classes
|
arise later. My view is that they have merit in defining interfaces to hardware
|
||||||
have merit in defining interfaces to hardware objects. You can be sure that
|
objects. You might be quite certain that your brometer will have only one
|
||||||
(for example) a Pyboard D will only have one RTC instance.
|
pressure sensor.
|
||||||
|
|
||||||
The advantage of a singleton is that it removes the need for a global instance
|
The advantage of a singleton is that it removes the need for a global instance
|
||||||
or for passing an instance between functions. The sole instance is retrieved at
|
or for passing an instance between functions. The sole instance is efficiently
|
||||||
any point in the code using constructor call syntax.
|
retrieved at any point in the code using function call syntax.
|
||||||
|
|
||||||
```python
|
```python
|
||||||
def singleton(cls):
|
def singleton(cls):
|
||||||
|
@ -33,8 +42,8 @@ ms = MySingleton(42) # prints 'In __init__ 42'
|
||||||
x = MySingleton() # No output: assign existing instance to x
|
x = MySingleton() # No output: assign existing instance to x
|
||||||
x.foo(5) # prints 'In foo 47': original state + 5
|
x.foo(5) # prints 'In foo 47': original state + 5
|
||||||
```
|
```
|
||||||
The first instantiation sets the object's initial state. Thereafter
|
The first call instantiates the object and sets its initial state. Subsequent
|
||||||
'instantiations' retrieve the original object.
|
calls retrieve the original object.
|
||||||
|
|
||||||
There are other ways of achieving singletons. One is to define a (notionally
|
There are other ways of achieving singletons. One is to define a (notionally
|
||||||
private) class in a module. The module API contains an access function. There
|
private) class in a module. The module API contains an access function. There
|
||||||
|
@ -73,7 +82,49 @@ class MyFunctor:
|
||||||
MyFunctor(42) # prints 'In __init__ 42'
|
MyFunctor(42) # prints 'In __init__ 42'
|
||||||
MyFunctor(5) # 'In __call__ 47'
|
MyFunctor(5) # 'In __call__ 47'
|
||||||
```
|
```
|
||||||
A use case is in asynchronous programming. The constructor launches a task:
|
A use case is in asynchronous programming. The constructor launches a
|
||||||
this will only occur once. Subsequent calls might alter the behaviour of that
|
continuously running task. Subsequent calls alter the behaviour of that task.
|
||||||
task. An example may be found
|
The following simple example has the task waiting for a period which can be
|
||||||
[in the Latency class](https://github.com/peterhinch/micropython-async/blob/master/lowpower/rtc_time.py).
|
changed at runtime:
|
||||||
|
|
||||||
|
```python
|
||||||
|
import uasyncio as asyncio
|
||||||
|
import pyb
|
||||||
|
|
||||||
|
def functor(cls):
|
||||||
|
instance = None
|
||||||
|
def getinstance(*args, **kwargs):
|
||||||
|
nonlocal instance
|
||||||
|
if instance is None:
|
||||||
|
instance = cls(*args, **kwargs)
|
||||||
|
return instance
|
||||||
|
return instance(*args, **kwargs)
|
||||||
|
return getinstance
|
||||||
|
|
||||||
|
@functor
|
||||||
|
class FooFunctor:
|
||||||
|
def __init__(self, led, interval):
|
||||||
|
self.led = led
|
||||||
|
self.interval = interval
|
||||||
|
asyncio.create_task(self._run())
|
||||||
|
|
||||||
|
def __call__(self, interval):
|
||||||
|
self.interval = interval
|
||||||
|
|
||||||
|
async def _run(self):
|
||||||
|
while True:
|
||||||
|
await asyncio.sleep_ms(self.interval)
|
||||||
|
# Do something useful here
|
||||||
|
self.led.toggle()
|
||||||
|
|
||||||
|
def go_fast(): # FooFunctor is available anywhere in this module
|
||||||
|
FooFunctor(100)
|
||||||
|
|
||||||
|
async def main():
|
||||||
|
FooFunctor(pyb.LED(1), 500)
|
||||||
|
await asyncio.sleep(3)
|
||||||
|
go_fast()
|
||||||
|
await asyncio.sleep(3)
|
||||||
|
|
||||||
|
asyncio.run(main())
|
||||||
|
```
|
||||||
|
|
Ładowanie…
Reference in New Issue