FAQ
Environment: Python 2.1 on Windows NT4 SPx (x== 5 or 6) with IE 4.0 (1)

In a Interpreter.py file :
class Interpreter:
....
# global procedures (module functions)
def onload(obj):
"""Init_fn of Interpret.py"""
if not getattr(obj, 'quiet', 1):
print "obj %s type %s\nclass %s isinstance %s" % (`obj`,
type(obj),obj.__class__,isinstance(obj, Interpreter) )
print "Interpreter %s\nrepr %s\ntype %s" % (Interpreter,
`Interpreter`,type(Interpreter))
# print "Interpreter %s __class__ %s" % (Interpreter,
Interpreter.__class__)
# assert isinstance(obj, Interpreter)
return (obj,) # tuple of objects
# Note that the assert isinstance is commented out

$ ../Python21/python.exe Interpreter.py
obj <__main__.Interpreter instance at 007F7CBC> type <type 'instance'>
class __main__.Interpreter isinstance 0
Interpreter Interpreter.Interpreter
repr <class Interpreter.Interpreter at 00843BDC>
type <type 'class'>

We are in the if __name__ == '__main__': case, obj has an attribute named
'quiet' which is false (in fact 0), it is an instance of Interpreter. The
onload function is called indirectly from the __init__ ctor of Interpreter.
no exception (no TypeError) but isinstance silently returns 0

I can live with the assert commented out, it seems that it is good practice
to avoid use of isinstance or of tests on the types, but I'd rather
understand why in this case isinstance returns false. I suspect some
namespace collision.

(1) Thank you MicroSoft for shipping some system components with an
application ==> It is practically impossible to assert the system's version.

Regards

---
Ce que l'on con?oit bien s'?nonce clairement,
Et les mots pour le dire arrivent ais?ment.
Boileau Despr?aux L'Art Po?tique. Chant I

Search Discussions

  • Francois Petitjean at Jan 31, 2002 at 8:30 am
    After some experiments, I found that :
    obj.__class__.__name__ == Interpreter.__name__ # 'Interpreter'

    I have added a direct call to the onload function :
    interp = Interpreter('stab', 0, 1) # The ctor calls onload(self) through
    a method call of a Module instance
    # direct call to onload
    print "\n"
    print onload(interp) # This time, isinstance(obj, Interpreter) is true!

    In the first case `Interpreter` is <class Interpreter.Interpreter at
    00843BDC>
    In the second case (direct call) : <class __main__.Interpreter at 007F924C>
    In the two cases obj is the same interp object (same address)

    Here is what the Interpreter.__init__(fname, quiet, dry_run) does :
    a) opens and reads fname+'.mdes' file.The content is decoded :
    module interpreteur << eom1
    description << eodescr
    This module contains the interpreter commands.

    For example:
    print a list of all commands
    print how to invoke a specific command
    print the documentation of a Module or a Command
    eodescr
    mod_name Interpreter
    fname_cdes builtin
    init_fn onload
    eom1
    ....
    [other module description]

    So a Module object is built with these informations. (the Module ctor reads
    and interprets the builtin.cdes file, it contains a list of Commands)

    b) instructs the first Module (named interpreteur) to import the mod_name
    python module, to check if an 'init_fn' function exists in this module and
    to call it with provided parameters *args, **kwargs.
    So, in the called Module method :
    mod_name = getattr(self, 'mod_name', self.name)
    self.module = __import__(mod_name)
    init_fn_name = getattr(self, 'init_fn', None)
    if init_fn_name:
    init_fn = getattr(self.module, init_fn_name, None)
    if callable(init_fn):
    mod_objs = (self.module,) + init_fn(*args, **kwargs) #
    Interpreter.onload(..) is called
    ....

    It seems that in "isinstance(obj, Interpreter)" the 'Interpreter'
    variable/symbol is bound to two different python objects (addresses are
    different). These two objects are two class Interpreter objects in different
    namespaces.

    Why the result of isinstance(object, cls) depends on the namespace in which
    cls lives? What is the proper way to "spell" cls?

    Regards
    PS Sorry for bad english, it is not my native language. I hope that I was
    clear.
  • Aahz Maruch at Jan 31, 2002 at 11:24 am
    In article <3c5717bb$0$23518$626a54ce at news.free.fr>,
    Francois Petitjean wrote:
    We are in the if __name__ == '__main__': case, obj has an attribute named
    'quiet' which is false (in fact 0), it is an instance of Interpreter. The
    onload function is called indirectly from the __init__ ctor of Interpreter.
    no exception (no TypeError) but isinstance silently returns 0
    You'll either need to post more code or reduce the code. Here's a
    trivial test:

    class X:
    def __init__(self):
    foo(self)

    def foo(y):
    print isinstance(y,X)

    x = X()
    foo(x)
    --
    --- Aahz <*> (Copyright 2002 by aahz at pobox.com)

    Hugs and backrubs -- I break Rule 6 http://www.rahul.net/aahz/
    Androgynous poly kinky vanilla queer het Pythonista

    "I got the new SPORT-UTILITY Segway." --Tom Toles
  • Francois Petitjean at Feb 1, 2002 at 6:20 am
    You'll either need to post more code or reduce the code
    Here is a trivial script (1) which highlights the problem :
    #!/usr/bin/env python
    """Fake Foo python module to test isinstance"""

    class Foo:
    def __init__(self):
    print "ctor " #,foo(self)

    def foo(o):
    return isinstance(o,Foo)

    def bar(o, modname='Foo'):
    """is o an instance of the class Foo in a module named modname"""
    mymod = __import__(modname) # or import Foo as mymod
    cls = mymod.Foo
    print "bar(o) %s %s" % ( isinstance(o,cls), `cls`)
    print "names? %s" % ( cls.__name__ == o.__class__.__name__, )

    if __name__ == '__main__':
    x = Foo()
    bar(x)
    print "foo(o) %s %s" % (foo(x), `Foo`)
    print "names? %s" % ( Foo.__name__ == x.__class__.__name__, )
    print `x`

    the output: (python 2.1.1 Windows NT4)
    $ ../Python21/python.exe Foo.py
    ctor
    bar(o) 0 <class Foo.Foo at 007CBABC>
    names? 1
    foo(o) 1 <class __main__.Foo at 007FCF9C>
    names? 1
    <__main__.Foo instance at 007FC2CC>

    This, IMHO, shows the "insistance" of "isinstance" to be very picky about
    its arguments. Or there is a pitfall in the handling of namespaces or
    import semantics which I don't know?

    Note that I am very aware that using isinstance or other type checking
    should be avoided if possible. But, I want eagerly to understand.

    (1) It is trivial as it has :
    only one module
    only one class
    only one instance
    and it uses only builtins and doesn't use 2.2 features.

    TIA
  • Jason Orendorff at Feb 1, 2002 at 6:31 am
    Francois:

    Try reading and running this little program
    and see if it clears anything up for you.

    # === foo.py
    class X:
    pass

    if __name__ == '__main__':
    import foo
    import __main__

    print foo is __main__
    print foo.X is __main__.X

    ## Jason Orendorff http://www.jorendorff.com/
  • Duncan Booth at Feb 1, 2002 at 9:21 am
    "Francois Petitjean" <littlejohn.75 at free.fr> wrote in
    news:3c5a3352$0$4604$626a54ce at news.free.fr:
    (1) It is trivial as it has :
    only one module
    Two modules, Foo and __main__
    only one class
    Two classes, one in each module. Foo.Foo and __main__.Foo
    only one instance
    and it uses only builtins and doesn't use 2.2 features.
    When you run a script, it executes the code in the context of the module
    called __main__. When you import a module it has a separate context even if
    the script and the module came out of the same source file. Importing a
    module executes each line in the file, even if you already ran most of them
    as a script.

    Every time you execute a class statement, even if the class name is the
    same, you create a new class.


    --
    Duncan Booth duncan at rcp.co.uk
    int month(char *p){return(124864/((p[0]+p[1]-p[2]&0x1f)+1)%12)["\5\x8\3"
    "\6\7\xb\1\x9\xa\2\0\4"];} // Who said my code was obscure?
  • Francois Petitjean at Feb 1, 2002 at 9:39 pm

    (1) It is trivial as it has :
    only one module
    Two modules, Foo and __main__
    yes, technically, but superficially a newbie can see only one.
    only one class
    Two classes, one in each module. Foo.Foo and __main__.Foo
    as a consequence of above
    When you run a script, it executes the code in the context of the module
    called __main__. When you import a module it has a separate context even if
    the script and the module came out of the same source file. Importing a
    module executes each line in the file, even if you already ran most of them
    as a script.
    I suppose that this context corresponds to a namespace, which is implemented
    internally by a dict.
    Where in the documentation is explained what means "Importing a module
    executes each line in the file". The lines are syntaxically checked, sure,
    but most of the work is not done at this stage:
    def curve(x):
    return return 10.0*math.sin(x)/x
    conversion to byte code.
    Every time you execute a class statement, even if the class name is the
    same, you create a new class.
    This is the crux of the problem, but after the first import, it seems that
    successive import of a module give the same class, due to the sys.module
    caching. Right?

    So, if I want to be on the safe side and to test a module Foo as it appears
    from outside, I can begin the __main__ part with import Foo. In this case,
    instanciation is of the form x = Foo.Foo(), all is good except for the
    doubling of the memory to store the class.

    Thank you for your insightful post.
  • Alex Martelli at Feb 1, 2002 at 10:22 pm
    Francois Petitjean wrote:
    ...
    Where in the documentation is explained what means "Importing a module
    executes each line in the file".
    Language reference manual.
    The lines are syntaxically checked, sure,
    but most of the work is not done at this stage:
    No, but every top-level statement is still executed.
    def curve(x):
    return return 10.0*math.sin(x)/x
    conversion to byte code.
    def is the top-level statement, and it's executed on import.
    Every time you execute a class statement, even if the class name is the
    same, you create a new class.
    This is the crux of the problem, but after the first import, it seems that
    successive import of a module give the same class, due to the sys.module
    caching. Right?
    Only if the imports use the same name. In your case, you were
    importing the same module as __main__ (implicitly) and foo
    (explicitly). sys.modules is checked with the modulename as
    the key, after all. (You may also choose to import with various
    modulenames -- check standard module imp for that, although
    you rarely need this). Note that "import x as y" is not an example:
    the module is imported (and set/checked in sys.modules) with
    a name 'x', it's only the local binding that uses 'y' here.

    So, if I want to be on the safe side and to test a module Foo as it
    appears from outside, I can begin the __main__ part with import Foo. In
    this case, instanciation is of the form x = Foo.Foo(), all is good except
    for the doubling of the memory to store the class.
    If all the top-level statements in the modules are OK to execute
    twice, yes. But if the top-level does e.g. an append to a file, you'll
    find two appends using this approach.


    Alex

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
grouppython-list @
categoriespython
postedJan 29, '02 at 9:46p
activeFeb 1, '02 at 10:22p
posts8
users5
websitepython.org

People

Translate

site design / logo © 2022 Grokbase