Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.python > #86025 > unrolled thread
| Started by | pfranken85@gmail.com |
|---|---|
| First post | 2015-02-21 04:15 -0800 |
| Last post | 2015-02-24 11:14 +1100 |
| Articles | 10 — 9 participants |
Back to article view | Back to comp.lang.python
Best practice: Sharing object between different objects pfranken85@gmail.com - 2015-02-21 04:15 -0800
Re: Best practice: Sharing object between different objects Dave Angel <davea@davea.name> - 2015-02-21 09:28 -0500
Re: Best practice: Sharing object between different objects Paul Rubin <no.email@nospam.invalid> - 2015-02-21 09:18 -0800
Re: Best practice: Sharing object between different objects Rob Gaddi <rgaddi@technologyhighland.invalid> - 2015-02-23 18:10 +0000
Re: Best practice: Sharing object between different objects Michael Torrie <torriem@gmail.com> - 2015-02-23 11:36 -0700
Re: Best practice: Sharing object between different objects sohcahtoa82@gmail.com - 2015-02-23 12:02 -0800
Re: Best practice: Sharing object between different objects Mark Lawrence <breamoreboy@yahoo.co.uk> - 2015-02-23 20:13 +0000
Re: Best practice: Sharing object between different objects Ian Kelly <ian.g.kelly@gmail.com> - 2015-02-23 13:39 -0700
Re: Best practice: Sharing object between different objects Michael Torrie <torriem@gmail.com> - 2015-02-23 14:10 -0700
Re: Best practice: Sharing object between different objects Chris Angelico <rosuav@gmail.com> - 2015-02-24 11:14 +1100
| From | pfranken85@gmail.com |
|---|---|
| Date | 2015-02-21 04:15 -0800 |
| Subject | Best practice: Sharing object between different objects |
| Message-ID | <aacac55a-6779-4ad3-96f4-5332ff36a365@googlegroups.com> |
Hello! I have a best-practice question: Imagine I have several hardware devices that I work with on the same I2C bus and I am using the python smbus module for that purpose. The individual devices are sensors, ADC, DAC components. As I said, I would like to derive the corresponding classes from one common class, let's say I2CDevice, so that they can share the same bus connection (I don't want to do a import smbus, ..., self.bus = smbus.SMBus(1) all the time). Of course, I could just pass the the bus reference to each instance, but I am pretty sure that there must be a nicer way to do this. In particular, I imagine the following: It should be possible that I have two classes, ADC_I2C, DAC_I2C which share the same base class. Once I create an instance of ADC_I2C or DAC_I2C it should check whether a bus object exists, if not, it should create one and the other class should be able to use this bus reference as well. Do you get my point? I am pretty sure that such a design pattern should exist, maybe also in the reference of DB connections? Unfortunately I did not find something like this. Any hints are highly appreciated! Thanks!
[toc] | [next] | [standalone]
| From | Dave Angel <davea@davea.name> |
|---|---|
| Date | 2015-02-21 09:28 -0500 |
| Message-ID | <mailman.18966.1424528921.18130.python-list@python.org> |
| In reply to | #86025 |
On 02/21/2015 07:15 AM, pfranken85@gmail.com wrote: > Hello! > > I have a best-practice question: Imagine I have several hardware devices that I work with on the same I2C bus and I am using the python smbus module for that purpose. The individual devices are sensors, ADC, DAC components. As I said, I would like to derive the corresponding classes from one common class, let's say I2CDevice, so that they can share the same bus connection (I don't want to do a import smbus, ..., self.bus = smbus.SMBus(1) all the time). Of course, I could just pass the the bus reference to each instance, but I am pretty sure that there must be a nicer way to do this. > > In particular, I imagine the following: It should be possible that I have two classes, ADC_I2C, DAC_I2C which share the same base class. Once I create an instance of ADC_I2C or DAC_I2C it should check whether a bus object exists, if not, it should create one and the other class should be able to use this bus reference as well. Do you get my point? I am pretty sure that such a design pattern should exist, maybe also in the reference of DB connections? Unfortunately I did not find something like this. > I think you should write the code (or at least a skeleton version). I suspect the answer will become obvious to you, once you're not worrying about design patterns, or being java compatible. Regardless of whether you inherit from a common base class, both classes can have an attribute with a "bus object" in it. The question becomes who initializes it, and who decides to reuse the "same one". Your wording doesn't make that the least bit clear to me; maybe your sample code will. Many times when you'd have a common base class in Java or C++, you just have to have a common member or two in Python. On the other hand, once you start implementing, maybe it'll become obvious that there's enough shared code for a common base class. The first question is whether an ADC "is-a" bus, or "has-a" bus. Stated that way it sounds like you should have an attribute in ADC which is a bus object. > Any hints are highly appreciated! > > Thanks! > -- DaveA
[toc] | [prev] | [next] | [standalone]
| From | Paul Rubin <no.email@nospam.invalid> |
|---|---|
| Date | 2015-02-21 09:18 -0800 |
| Message-ID | <87sidzchdq.fsf@jester.gateway.pace.com> |
| In reply to | #86025 |
pfranken85@gmail.com writes:
> ADC, DAC components. As I said, I would like to derive the
> corresponding classes from one common class, let's say I2CDevice, so
> that they can share the same bus connection (I don't want to do a
> import smbus, ..., self.bus = smbus.SMBus(1) all the time).
I don't really understand the question but it sounds like you might
want a class variable:
import smbus
class I2CDevice
bus = smbus.SMBus(1)
def __init__ (self): ...
This puts the "bus" object into the I2CDevice class itself. It is
created when the I2CDevice class is defined. Methods wanting to access
it can then say
do_something_with(I2CDevice.bus)
is that what you wanted?
[toc] | [prev] | [next] | [standalone]
| From | Rob Gaddi <rgaddi@technologyhighland.invalid> |
|---|---|
| Date | 2015-02-23 18:10 +0000 |
| Message-ID | <mcfqeb$5tb$1@dont-email.me> |
| In reply to | #86025 |
On Sat, 21 Feb 2015 04:15:50 -0800, pfranken85 wrote: > Hello! > > I have a best-practice question: Imagine I have several hardware devices > that I work with on the same I2C bus and I am using the python smbus > module for that purpose. The individual devices are sensors, ADC, DAC > components. As I said, I would like to derive the corresponding classes > from one common class, let's say I2CDevice, so that they can share the > same bus connection (I don't want to do a import smbus, ..., self.bus = > smbus.SMBus(1) all the time). Of course, I could just pass the the bus > reference to each instance, but I am pretty sure that there must be a > nicer way to do this. > > In particular, I imagine the following: It should be possible that I > have two classes, ADC_I2C, DAC_I2C which share the same base class. Once > I create an instance of ADC_I2C or DAC_I2C it should check whether a bus > object exists, if not, it should create one and the other class should > be able to use this bus reference as well. Do you get my point? I am > pretty sure that such a design pattern should exist, maybe also in the > reference of DB connections? Unfortunately I did not find something like > this. > > Any hints are highly appreciated! > > Thanks! So my experience doing similar work is with VMEBus, but if I were trying to do what you're doing, I'd take advantage of the fact that hardware isn't nearly as abstract as software. SMBus(1) represents three physical contiguous pieces of copper on a PCB somewhere. So I'd solve it with module level global variables. It's semi-frowned upon on software stuff because it creates an unintentional shared state between different modules, but you really HAVE a shared state, so it needs to be dealt with. So I'd put your ADC and DAC in the same package, whether all in one file or all in a package folder, and I'd give that package a: def getSMBus(busnumber): that takes care of the management of only creating each bus once. Then I'd give each class a: def __init__(busnumber): self.bus = getSMBus(busnumber) You could commonize that by deriving both classes from a common ancestor (all my VME modules derive from a common Region), but with only one piece of shared code between I don't think I'd bother. If you did, you could make the getSMBus code a classmethod just to make clear the lack of dependency on individual instances, but that starts to be code for code's sake. -- Rob Gaddi, Highland Technology -- www.highlandtechnology.com Email address domain is currently out of order. See above to fix.
[toc] | [prev] | [next] | [standalone]
| From | Michael Torrie <torriem@gmail.com> |
|---|---|
| Date | 2015-02-23 11:36 -0700 |
| Message-ID | <mailman.19095.1424717125.18130.python-list@python.org> |
| In reply to | #86250 |
On 02/23/2015 11:10 AM, Rob Gaddi wrote: > So I'd solve it with module level global variables. It's semi-frowned > upon on software stuff because it creates an unintentional shared state > between different modules, but you really HAVE a shared state, so it > needs to be dealt with. I would also do it with a module attribute. In my mind that's exactly the right way to go. But I disagree that it's frowned on or a bad thing. A module is a completely appropriate place to store state. In fact a module is an object, but a special one that can only be instantiated once. So as far as patterns go, a module is a singleton. Almost any time in Python you have something that you want to have exactly one instance of in your program, you don't want to define a class but rather just use a module. Any code in a module can be considered the constructor. It executes only once in your program when the module is first imported, no matter how many times its imported after that. I often use a module to store configuration that is shared across modules in my projects.
[toc] | [prev] | [next] | [standalone]
| From | sohcahtoa82@gmail.com |
|---|---|
| Date | 2015-02-23 12:02 -0800 |
| Message-ID | <ac52606e-f85f-4e94-8dac-6556e28821be@googlegroups.com> |
| In reply to | #86254 |
On Monday, February 23, 2015 at 10:45:59 AM UTC-8, Michael Torrie wrote: > On 02/23/2015 11:10 AM, Rob Gaddi wrote: > > So I'd solve it with module level global variables. It's semi-frowned > > upon on software stuff because it creates an unintentional shared state > > between different modules, but you really HAVE a shared state, so it > > needs to be dealt with. > > I would also do it with a module attribute. In my mind that's exactly > the right way to go. > > But I disagree that it's frowned on or a bad thing. A module is a > completely appropriate place to store state. In fact a module is an > object, but a special one that can only be instantiated once. So as far > as patterns go, a module is a singleton. Almost any time in Python you > have something that you want to have exactly one instance of in your > program, you don't want to define a class but rather just use a module. > > Any code in a module can be considered the constructor. It executes only > once in your program when the module is first imported, no matter how > many times its imported after that. > > I often use a module to store configuration that is shared across > modules in my projects. That behavior always trips me up. My intuition tells me that every time you import a module, it re-runs the code in the module. So if I had a simple module named myModule.py that had a single line with `myInt = 1`, then I would *EXPECT* this behavior: >>> import myModule >>> myModule.myInt 1 >>> myModule.myInt = 2 >>> myModule.myInt 2 >>> import myModule >>> myModule.myInt 1 It seems slightly counter-intuitive, but the *ACTUAL* behavior (where the final line prints 2) does allow for something nice: Easy use of global variables. What's REALLY interesting is that this happens: >>> import myModule >>> myModule.myInt 1 >>> myModule.myInt = 2 >>> myModule.myInt 2 >>> del myModule >>> import myModule >>> myModule.myInt 2 I would REALLY expect that deleting the module object and then re-importing would reset that variable. And then... >>> del myModule.myInt >>> del myModule >>> import myModule >>> myModule.myInt Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: 'module' object has no attribute 'myInt' So yeah...modules are really only loaded once unless you use reload/imp.reload/importlib.reload. But yeah, it seems slightly counter-intuitive to me at first, but certainly has its uses.
[toc] | [prev] | [next] | [standalone]
| From | Mark Lawrence <breamoreboy@yahoo.co.uk> |
|---|---|
| Date | 2015-02-23 20:13 +0000 |
| Message-ID | <mailman.19099.1424722435.18130.python-list@python.org> |
| In reply to | #86259 |
On 23/02/2015 20:02, sohcahtoa82@gmail.com wrote: > On Monday, February 23, 2015 at 10:45:59 AM UTC-8, Michael Torrie wrote: >> On 02/23/2015 11:10 AM, Rob Gaddi wrote: >>> So I'd solve it with module level global variables. It's semi-frowned >>> upon on software stuff because it creates an unintentional shared state >>> between different modules, but you really HAVE a shared state, so it >>> needs to be dealt with. >> >> I would also do it with a module attribute. In my mind that's exactly >> the right way to go. >> >> But I disagree that it's frowned on or a bad thing. A module is a >> completely appropriate place to store state. In fact a module is an >> object, but a special one that can only be instantiated once. So as far >> as patterns go, a module is a singleton. Almost any time in Python you >> have something that you want to have exactly one instance of in your >> program, you don't want to define a class but rather just use a module. >> >> Any code in a module can be considered the constructor. It executes only >> once in your program when the module is first imported, no matter how >> many times its imported after that. >> >> I often use a module to store configuration that is shared across >> modules in my projects. > > That behavior always trips me up. My intuition tells me that every time you import a module, it re-runs the code in the module. So if I had a simple module named myModule.py that had a single line with `myInt = 1`, then I would *EXPECT* this behavior: > >>>> import myModule >>>> myModule.myInt > 1 >>>> myModule.myInt = 2 >>>> myModule.myInt > 2 >>>> import myModule >>>> myModule.myInt > 1 > > It seems slightly counter-intuitive, but the *ACTUAL* behavior (where the final line prints 2) does allow for something nice: Easy use of global variables. > > What's REALLY interesting is that this happens: > >>>> import myModule >>>> myModule.myInt > 1 >>>> myModule.myInt = 2 >>>> myModule.myInt > 2 >>>> del myModule >>>> import myModule >>>> myModule.myInt > 2 > > I would REALLY expect that deleting the module object and then re-importing would reset that variable. And then... > >>>> del myModule.myInt >>>> del myModule >>>> import myModule >>>> myModule.myInt > Traceback (most recent call last): > File "<stdin>", line 1, in <module> > AttributeError: 'module' object has no attribute 'myInt' > > So yeah...modules are really only loaded once unless you use reload/imp.reload/importlib.reload. > > But yeah, it seems slightly counter-intuitive to me at first, but certainly has its uses. > Rule 1) Don't expect anything of Python, always read the docs. Rule 2) If in doubt always refer to rule 1) -- My fellow Pythonistas, ask not what our language can do for you, ask what you can do for our language. Mark Lawrence
[toc] | [prev] | [next] | [standalone]
| From | Ian Kelly <ian.g.kelly@gmail.com> |
|---|---|
| Date | 2015-02-23 13:39 -0700 |
| Message-ID | <mailman.19100.1424724040.18130.python-list@python.org> |
| In reply to | #86259 |
On Mon, Feb 23, 2015 at 1:02 PM, <sohcahtoa82@gmail.com> wrote: > What's REALLY interesting is that this happens: > >>>> import myModule >>>> myModule.myInt > 1 >>>> myModule.myInt = 2 >>>> myModule.myInt > 2 >>>> del myModule >>>> import myModule >>>> myModule.myInt > 2 > > I would REALLY expect that deleting the module object and then re-importing would reset that variable. Even though you deleted the module locally, it's still referenced in the sys.modules cache (as well as in any other place where it might have been imported). That's the place you need to delete it from if you really want to re-execute it. >>> import myModule >>> myModule.myInt 1 >>> myModule.myInt = 2 >>> myModule.myInt 2 >>> import sys >>> del sys.modules['myModule'] >>> import myModule >>> myModule.myInt 1
[toc] | [prev] | [next] | [standalone]
| From | Michael Torrie <torriem@gmail.com> |
|---|---|
| Date | 2015-02-23 14:10 -0700 |
| Message-ID | <mailman.19102.1424725814.18130.python-list@python.org> |
| In reply to | #86259 |
On 02/23/2015 01:02 PM, sohcahtoa82@gmail.com wrote: > That behavior always trips me up. My intuition tells me that every > time you import a module, it re-runs the code in the module. So if I > had a simple module named myModule.py that had a single line with > `myInt = 1`, then I would *EXPECT* this behavior: Basically your intuition is wrong, but I'm not really sure why you think this in the first place, especially if you're familiar with design patterns. A module is a singleton. Plain and simple. If you expect a module to reinstantiate something every time you import it, then what you want is a class, not a module. Even if you think of modules like C header files, as far as use goes, you wouldn't be too far wrong. Generally speaking header files are processed only once no matter how many times they are included (at least the common ones with #ifdef fences in them). I can see how coming from PHP would trip you up, though. Of course I never got the hang of include vs include_once vs require vs require_once.
[toc] | [prev] | [next] | [standalone]
| From | Chris Angelico <rosuav@gmail.com> |
|---|---|
| Date | 2015-02-24 11:14 +1100 |
| Message-ID | <mailman.19108.1424736906.18130.python-list@python.org> |
| In reply to | #86259 |
On Tue, Feb 24, 2015 at 8:10 AM, Michael Torrie <torriem@gmail.com> wrote: > On 02/23/2015 01:02 PM, sohcahtoa82@gmail.com wrote: >> That behavior always trips me up. My intuition tells me that every >> time you import a module, it re-runs the code in the module. So if I >> had a simple module named myModule.py that had a single line with >> `myInt = 1`, then I would *EXPECT* this behavior: > > I can see how coming from PHP would trip you up, though. Of course I > never got the hang of include vs include_once vs require vs require_once. If you think of "import" as "go and grab this file of code and run it" (like PHP's include or a preprocessor #include directive), then yes, you would expect that. But think of it, instead, as "give me access to this feature". If that feature doesn't yet exist, Python will go and fetch it up; but if it does, yay! You now have access, really quickly and easily. ChrisA
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.python
csiph-web