Module imports during object instantiation

R

Ritesh Raj Sarraf

Hi,

I've been very confused about why this doesn't work. I mean I don't see any
reason why this has been made not to work.

class Log:

def __init__(self, verbose, lock = None):

if verbose is True:
self.VERBOSE = True
else: self.VERBOSE = False


if lock is None or lock != 1:
self.DispLock = False
else:
self.DispLock = threading.Lock()
self.lock = True

if os.name == 'posix':
self.platform = 'posix'
self.color = get_colors()

elif os.name in ['nt', 'dos']:
self.platform = 'microsoft'

try:
import SomeModule
except ImportError:
self.Set_Flag = None

if self.Set_Flag is not None:
self.color = SomeModule.get_colors_windows()

else:
self.platform = None
self.color = None

When I create an object the "import" part never gets executed. Is there a
reason behind it ?
I mean I'd like to keep my class as independent as I want. So that when
later I need to use it somewhere else, I don't need to know if it depends
on any modules.

Currently, the way I'm left is to globally go and import the module and set
a flag there.


Ritesh
 
J

James Stroud

Ritesh said:
Hi,

I've been very confused about why this doesn't work. I mean I don't see any
reason why this has been made not to work.

class Log:

def __init__(self, verbose, lock = None):

if verbose is True:
self.VERBOSE = True
else: self.VERBOSE = False


if lock is None or lock != 1:
self.DispLock = False
else:
self.DispLock = threading.Lock()
self.lock = True

if os.name == 'posix':
self.platform = 'posix'
self.color = get_colors()

elif os.name in ['nt', 'dos']:
self.platform = 'microsoft'

try:
import SomeModule
except ImportError:
self.Set_Flag = None

if self.Set_Flag is not None:
self.color = SomeModule.get_colors_windows()

else:
self.platform = None
self.color = None

When I create an object the "import" part never gets executed. Is there a
reason behind it ?
I mean I'd like to keep my class as independent as I want. So that when
later I need to use it somewhere else, I don't need to know if it depends
on any modules.

Currently, the way I'm left is to globally go and import the module and set
a flag there.


Ritesh

You do realize your import statement will only be called for nt and dos
systems don't you?

James

--
James Stroud
UCLA-DOE Institute for Genomics and Proteomics
Box 951570
Los Angeles, CA 90095

http://www.jamesstroud.com/
 
R

Ritesh Raj Sarraf

You do realize your import statement will only be called for nt and dos
systems don't you?

Yes. I would like to load a Windows Python Module (which is, say a
specific implementation for Windows only) in such a condition where I
find that the platform is Dos/NT.

Loading it globally doesn't make sense because when from the same
class an object is created on a non-windows platfom, it would be
waste. It would either ImportError or else just load the module and
never use it.

As per my understanding __init__ is executed only once during object
creation. For such situations (that I've explained above), I think
__init__() is the correct place to put imports.

Ritesh
 
B

Bruno Desthuilliers

Ritesh Raj Sarraf a écrit :
Hi,

I've been very confused about why this doesn't work. I mean I don't see any
reason why this has been made not to work.

class Log:

def __init__(self, verbose, lock = None):

if verbose is True:

Don't use an identity test here. There are quite a lot of values that
eval to either True or False in a boolean context without being the True
or False objects.
self.VERBOSE = True
else: self.VERBOSE = False

Also, this test is rather dumb - in fact you just don't need any test:

self.VERBOSE = bool(verbose)
if lock is None or lock != 1:
self.DispLock = False
else:
self.DispLock = threading.Lock()
self.lock = True

if os.name == 'posix':
self.platform = 'posix'
self.color = get_colors()

elif os.name in ['nt', 'dos']:
self.platform = 'microsoft'

try:
import SomeModule
except ImportError:
self.Set_Flag = None

if self.Set_Flag is not None:
self.color = SomeModule.get_colors_windows()

else:
self.platform = None
self.color = None

When I create an object the "import" part never gets executed. Is there a
reason behind it ?

what does "print os.name" yields ?
I mean I'd like to keep my class as independent as I want. So that when
later I need to use it somewhere else, I don't need to know if it depends
on any modules.
>

Then pass the module to the initializer. Python's modules are objects...
 
B

Bruno Desthuilliers

Ritesh Raj Sarraf a écrit :
Yes. I would like to load a Windows Python Module (which is, say a
specific implementation for Windows only) in such a condition where I
find that the platform is Dos/NT.

Loading it globally doesn't make sense because when from the same
class an object is created on a non-windows platfom, it would be
waste. It would either ImportError or else just load the module and
never use it.

As per my understanding __init__ is executed only once during object
creation. For such situations (that I've explained above), I think
__init__() is the correct place to put imports.


Nope.

The initializer will be called *each time* you instanciate the class.
And nothing prevents client code from calling it explicitelly as many
times as it wants - ok, this would be rather strange, but this is still
technically possible. What I mean that you have no assurance about the
number of times an initializer will be called.


wrt/ your problem, remember that top-level code is executed when the
module is loaded (either as a main program or as an imported module).
The canonical solution to os-specific imports is to handle them at the
top-level:

if os.name == 'posix:
from some_posix_module import get_colors
elif os.name in ['nt', 'dos']:
from some_nt_module import get_windows_color as get_colors
else:
get_colors = lambda: None # or any other sensible default value...

class SomeClass(object):
def __init__(self, *args, **kw):
self.colors = get_colors()
 
R

Ritesh Raj Sarraf

Bruno said:
Ritesh Raj Sarraf a écrit :

The initializer will be called *each time* you instanciate the class.
And nothing prevents client code from calling it explicitelly as many
times as it wants - ok, this would be rather strange, but this is still
technically possible. What I mean that you have no assurance about the
number of times an initializer will be called.

Yes, it should be called _each time_ I do an instantiation. But the point
is, I'm doing it only once. And I don't see people instantiating multiple
times. And even if you do, it should do separate imports.

log1 = Log()
log2 = Log()

Both the objects are separate from each other in every manner and they share
nothing.
wrt/ your problem, remember that top-level code is executed when the
module is loaded (either as a main program or as an imported module).
The canonical solution to os-specific imports is to handle them at the
top-level:

if os.name == 'posix:
from some_posix_module import get_colors
elif os.name in ['nt', 'dos']:
from some_nt_module import get_windows_color as get_colors
else:
get_colors = lambda: None # or any other sensible default value...

class SomeClass(object):
def __init__(self, *args, **kw):
self.colors = get_colors()

This is what I'm left with to do currently. But I doubt if that makes by
classes independent and to "Just Work". If someone was to cut/paste just
the class, it won't work. He'll have to go through the imports and figure
out which one relates to the class he want's to import and add similar code
to his.

Ritesh
 
R

Ritesh Raj Sarraf

Bruno said:
Ritesh Raj Sarraf a écrit :
if lock is None or lock != 1:
self.DispLock = False
else:
self.DispLock = threading.Lock()
self.lock = True

if os.name == 'posix':
self.platform = 'posix'
self.color = get_colors()

elif os.name in ['nt', 'dos']:
self.platform = 'microsoft'

try:
import SomeModule
except ImportError:
self.Set_Flag = None

if self.Set_Flag is not None:
self.color = SomeModule.get_colors_windows()

else:
self.platform = None
self.color = None

When I create an object the "import" part never gets executed. Is there a
reason behind it ?

what does "print os.name" yields ?

On Windows: nt
On Linux: posix
Then pass the module to the initializer. Python's modules are objects...

Yes, that's an option. But is that the only one?
To me it looks like an ugly way of doing.

Ritesh
 
B

Bruno Desthuilliers

Ritesh Raj Sarraf a écrit :
Yes, it should be called _each time_ I do an instantiation. But the point
is, I'm doing it only once. And I don't see people instantiating multiple
times.

You of course don't instanciate the same object more than once !-) What
I meant is that, while you can be reasonably confident that the
initializer will be call at least once (on instanciation), nothing
prevents user code to directly call it as many times he wants.
And even if you do, it should do separate imports.

Why so ? Using the import statement, modules are only imported once for
a given process, you know ? And FWIW, what are the chances your running
process will move from one platform to another ?-)
log1 = Log()
log2 = Log()

Both the objects are separate from each other in every manner and they share
nothing.

How can you tell ? In the common case, they at least share a pointer to
the Log class object, and depending on the implementation they can share
other things too.
wrt/ your problem, remember that top-level code is executed when the
module is loaded (either as a main program or as an imported module).
The canonical solution to os-specific imports is to handle them at the
top-level:

if os.name == 'posix:
from some_posix_module import get_colors
elif os.name in ['nt', 'dos']:
from some_nt_module import get_windows_color as get_colors
else:
get_colors = lambda: None # or any other sensible default value...

class SomeClass(object):
def __init__(self, *args, **kw):
self.colors = get_colors()

This is what I'm left with to do currently. But I doubt if that makes by
classes independent and to "Just Work". If someone was to cut/paste just
the class, it won't work.

Obviously not. But the module is the basic unit of code in Python.
He'll have to go through the imports and figure
out which one relates to the class he want's to import and add similar code
to his.

I'm afraid you're confusing import, include and cut'n'paste (which is
probably the worst possible code-reuse technic)... If someone wants to
reuse your code, the normal way is to import your module (and eventually
subclass yourmodule.SomeClass to extend/customize it).
 
B

Bruno Desthuilliers

Ritesh Raj Sarraf a écrit :
Bruno said:
Ritesh Raj Sarraf a écrit :
if lock is None or lock != 1:
self.DispLock = False
else:
self.DispLock = threading.Lock()
self.lock = True

if os.name == 'posix':
self.platform = 'posix'
self.color = get_colors()

elif os.name in ['nt', 'dos']:
self.platform = 'microsoft'

try:
import SomeModule
except ImportError:
self.Set_Flag = None

if self.Set_Flag is not None:
self.color = SomeModule.get_colors_windows()

else:
self.platform = None
self.color = None

When I create an object the "import" part never gets executed. Is there a
reason behind it ?
what does "print os.name" yields ?

On Windows: nt
On Linux: posix

Mmm... I guess you didn't understood my question. I do know the os
module. You assert the "import" is never executed. Since it's only
executed on a non-posix platform, I asked on what platform you where
testing.

Yes, that's an option. But is that the only one?
No.

To me it looks like an ugly way of doing.

Really ? Why so ? You say you want to keep your class "as independant"
(you don't say from what, but...). Can you imagine a way to get less
coupling than passing appropriate parameters to the initializer ?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,743
Messages
2,569,478
Members
44,899
Latest member
RodneyMcAu

Latest Threads

Top