FAQ
hi there,

I'd like to provide a hierarchy of config data by means of
nested classes and static variables, such as:

class A:
prefix='usr/local'
class B:
datadir = A.prefix + '/share'
...

however, I get a NameError: name 'A' is not defined

What am I doing wrong ? The above is possibly a bit driven
by my C++ programming style. What is the python way of doing
this ?

Thanks,
Stefan

Search Discussions

  • Alex Martelli at Jun 18, 2001 at 4:05 pm
    "Stefan Seefeld" <seefeld at sympatico.ca> wrote in message
    news:3B2E2D3A.75F329D at sympatico.ca...
    hi there,

    I'd like to provide a hierarchy of config data by means of
    nested classes and static variables, such as:

    class A:
    prefix='usr/local'
    class B:
    datadir = A.prefix + '/share'
    ...

    however, I get a NameError: name 'A' is not defined
    class-object A does not yet exist (and thus in particular
    its name is not yet bound to it) until its classbody has
    _finished_ executing.

    You could do something like:

    class A:
    prefix = '/usr/local'
    class B:
    pass # or whatever...
    B.datadir = prefix + '/share'


    Alex
  • Gbreed at Jun 18, 2001 at 5:08 pm
    In article <3B2E2D3A.75F329D at sympatico.ca>, seefeld at sympatico.ca
    (Stefan Seefeld) wrote:
    hi there,

    I'd like to provide a hierarchy of config data by means of
    nested classes and static variables, such as:

    class A:
    prefix='usr/local'
    class B:
    datadir = A.prefix + '/share'
    ...

    however, I get a NameError: name 'A' is not defined
    See the earlier message "getting a reference to a class inside
    its definition" and the flood of no good ideas at all that
    followed it.
    What am I doing wrong ? The above is possibly a bit driven
    by my C++ programming style. What is the python way of doing
    this ?
    You can get that to work in C++? It looks strange to me, I'm
    sure you can't be trying to do what you think you're trying to
    do. This is the nearest I can think of that works:
    class A:
    ... prefix = 'usr/local'
    ...
    class B(A):
    ... datadir = A.prefix+'/share'
    ...
    A.prefix
    'usr/local'
    B.datadir
    'usr/local/share'


    You may also like to take a look at os.path.join
    import os.path
    class A:
    ... prefix = os.path.join('usr','local')
    ...
    class B(A):
    ... datadir = os.path.join(A.prefix, 'share')
    ...
    print A.prefix
    usr\local
    print B.datadir
    usr\local\share
    print B.prefix
    usr\local

    It'll give the right results on a UNIX system, and stop double
    or omitted slashes.

    Graham
  • Stefan Seefeld at Jun 18, 2001 at 6:23 pm

    gbreed at cix.compulink.co.uk wrote:

    What am I doing wrong ? The above is possibly a bit driven
    by my C++ programming style. What is the python way of doing
    this ?
    You can get that to work in C++? It looks strange to me, I'm
    sure you can't be trying to do what you think you're trying to
    do. This is the nearest I can think of that works:
    uh, what do *you* think that I'm trying to do, then ? :)

    What I'm arguing about is a matter of name resolution. I sure
    can open a scope 'A' in C++, insert a new scope 'B' into it,
    and from within that access other symbols declared in scope 'A'.
    In fact, I don't need to qualify them (i.e. 'foo' instead of 'A::foo'
    for any symbol 'foo' in the scope 'A' is just fine) if I'm inside
    that scope, no matter how deeply nested (of course, as long as there
    are no ambiguities).


    class A:
    ... prefix = 'usr/local'
    ...
    class B(A):
    ... datadir = A.prefix+'/share'
    ...
    A.prefix
    'usr/local'
    B.datadir
    'usr/local/share'
    ok, that works because B derives from A, i.e. the definition of 'A'
    is complete at the point where B's definition starts.
    class A:
    ... prefix = os.path.join('usr','local')
    ...
    class B(A):
    ... datadir = os.path.join(A.prefix, 'share')
    good idea, thanks. the original 'prefix' stems from 'configure', i.e.
    my python file 'foo.py' is generated from 'foo.py.in' by means of the
    autotools (autoconf, configure, ...)

    Thanks,
    Stefan
  • Mats Wichmann at Jun 18, 2001 at 11:07 pm

    On Mon, 18 Jun 2001 13:23:33 -0500, Stefan Seefeld wrote:

    gbreed at cix.compulink.co.uk wrote:
    What am I doing wrong ? The above is possibly a bit driven
    by my C++ programming style. What is the python way of doing
    this ?
    You can get that to work in C++? It looks strange to me, I'm
    sure you can't be trying to do what you think you're trying to
    do. This is the nearest I can think of that works:
    uh, what do *you* think that I'm trying to do, then ? :)

    What I'm arguing about is a matter of name resolution. I sure
    can open a scope 'A' in C++, insert a new scope 'B' into it,
    and from within that access other symbols declared in scope 'A'.
    In fact, I don't need to qualify them (i.e. 'foo' instead of 'A::foo'
    for any symbol 'foo' in the scope 'A' is just fine) if I'm inside
    that scope, no matter how deeply nested (of course, as long as there
    are no ambiguities).
    Java and C++ are compiled. The class definition is instructions to
    the compiler, and can be self-referential, because the /reference/ is
    not going to happen until the class is loaded - no inconsistency. Not
    so for Python, the class definition is code that is actually run to
    build the class object, and before that object has been built, there's
    nothing to refer to yet, as Alex said.
  • Rainer Deyke at Jun 19, 2001 at 2:25 am
    "Mats Wichmann" <xyzmats at laplaza.org> wrote in message
    news:3b2e8989.32036776 at news.laplaza.org...
    Java and C++ are compiled. The class definition is instructions to
    the compiler, and can be self-referential, because the /reference/ is
    not going to happen until the class is loaded - no inconsistency. Not
    so for Python, the class definition is code that is actually run to
    build the class object, and before that object has been built, there's
    nothing to refer to yet, as Alex said.
    That's the way it is now, but it doesn't have to be that way. Consider
    modules. Circular references between modules work because the module object
    is created and added to 'sys.modules' before any code in the module is
    executed:

    # A.py:
    # Module 'A' already exists when the following line executes.
    import B

    # B.py:
    import A


    The same principle could be applied to classes, though that isn't
    necessarily a good idea.



    --
    Rainer Deyke (root at rainerdeyke.com)
    Shareware computer games - http://rainerdeyke.com
    "In ihren Reihen zu stehen heisst unter Feinden zu kaempfen" - Abigor
  • Marcin 'Qrczak' Kowalczyk at Jun 21, 2001 at 5:00 pm

    Mon, 18 Jun 2001 23:07:07 GMT, Mats Wichmann <xyzmats at laplaza.org> pisze:

    Java and C++ are compiled. The class definition is instructions to
    the compiler, and can be self-referential, because the /reference/ is
    not going to happen until the class is loaded - no inconsistency.
    Being compiled is not necessary to be able to self-reference
    everything. Haskell and Clean are usually compiled, but when they are
    interpreted, they work the same way: because they use lazy evaluation,
    it's normal to have every name defined in a group visible in all
    the bodies.

    This applies to all value definitions, not only to functions, even if
    it's nonsensical, i.e. 'let x = y+1; y = x+1 in x' is only a runtime
    error or an infinite loop.

    --
    __("< Marcin Kowalczyk * qrczak at knm.org.pl http://qrczak.ids.net.pl/
    \__/
    ^^ SYGNATURA ZAST?PCZA
    QRCZAK
  • Gbreed at Jun 19, 2001 at 2:21 pm
    In article <3B2E4725.535AB18E at sympatico.ca>,
    seefeld at sympatico.ca (Stefan Seefeld) wrote:
    uh, what do *you* think that I'm trying to do, then ? :)
    Beats me :)
    What I'm arguing about is a matter of name resolution. I sure
    can open a scope 'A' in C++, insert a new scope 'B' into it,
    and from within that access other symbols declared in scope 'A'.
    In fact, I don't need to qualify them (i.e. 'foo' instead of 'A::foo'
    for any symbol 'foo' in the scope 'A' is just fine) if I'm inside
    that scope, no matter how deeply nested (of course, as long as there
    are no ambiguities).
    You're correct, I've found an example

    <http://oopsla.snu.ac.kr/c++/cpplecture/chap5/node22.html>

    and an argument against them

    <http://www.elj.com/eiffel/ij/nested-classes/>

    But my head still spins when I try to think of a C++ class that
    hasn't been instantiated. C++'s nested classes seem to be a
    special case of what Java's inner classes do, so check the
    thread on those.

    Here's another try:

    class A:
    def __init__(self):
    self.prefix = 'usr/local'
    class __B:
    def __init__(self, parent):
    self.prefix = os.path.join(parent.prefix, 'share')
    def B(self):
    return self.__B(self)

    print A().prefix
    print A().B().prefix

    You could remember the parent, but that'd lead to a circular
    reference (not such a bad thing for 2.x).

    Which means the same purpose would be served by

    class FileNode:
    """holds a prefix"""

    A = FileNode()
    A.prefix = 'usr/local'
    A.B = FileNode()
    A.B.prefix = os.path.join(A.prefix,'share')

    print A.prefix
    print A.B.prefix


    No problem about the namespace, because it's always explicit.

    Or

    class FileNode:
    def __init__(self, prefix):
    self.prefix = prefix
    def addNode(self, name, prefix):
    setattr(self, name,
    FileNode(os.path.join(self.prefix, prefix)))

    A = FileNode('usr/local')
    A.addNode('B','share')

    print A.prefix
    print A.B.prefix


    Or

    class FileNode:
    def __init__(self, prefix):
    self.prefix = prefix
    def newChildNode(self, prefix):
    return FileNode(os.path.join(self.prefix, prefix))

    A = FileNode('usr/local')
    A.B = A.newChildNode('share')

    print A.prefix
    print A.B.prefix


    Perhaps if you give us C++ code of what you're trying to do, we
    can tell you why you don't need to do it ;)


    Graham
  • Alex Martelli at Jun 19, 2001 at 3:27 pm
    <gbreed at cix.compulink.co.uk> wrote in message
    news:9gnn5c$b00$1 at plutonium.compulink.co.uk...
    ...
    You could remember the parent, but that'd lead to a circular
    reference (not such a bad thing for 2.x).
    Still, reference cycles may be best avoided -- module
    weakref (in 2.1) does that well!


    Alex
  • Stefan Seefeld at Jun 19, 2001 at 8:14 pm

    gbreed at cix.compulink.co.uk wrote:

    You're correct, I've found an example

    <http://oopsla.snu.ac.kr/c++/cpplecture/chap5/node22.html>

    and an argument against them

    <http://www.elj.com/eiffel/ij/nested-classes/>
    ok, well, this is a python list so let's not turn this into a C++
    discussion. However, the above link contains a couple of wrong
    statements. To get this back on track, only this:

    class nesting uses the fact that a class (in C++) acts as an ordinary
    scope, so you can use it the same way as a namespace, to bind names
    to a common scope, and avoid name clashes if the name you want to define
    is general, but has a specific meaning in the scope within which you want
    to use it. ('Geometry::Point' for example).

    Back to my python code:

    I tried to mirror the structure of a package I provide ('Synopsis') in
    a Config class. Since the synopsis tool is very modular, each submodule
    contains its own set of parameters which you might want to configure.
    Passing all of them as command line options will quickly get very messy,
    so we figured we might just provide the possibility to write a config
    script that sets all the flags/options at the right scope. For example:
    Some options apply to more than one module, so it appears natural to
    define it in an 'outer scope'. This, however, assumes that 'inner scopes'
    (aka nested classes) can see the variables defined in outer scopes.

    I hope this somewhat explains what I'm aiming at...

    But my head still spins when I try to think of a C++ class that
    hasn't been instantiated.
    Again, we are talking about classes as scopes, not class instances.
    class A:
    def __init__(self):
    self.prefix = 'usr/local'
    class __B:
    def __init__(self, parent):
    self.prefix = os.path.join(parent.prefix, 'share')
    def B(self):
    return self.__B(self)

    print A().prefix
    print A().B().prefix

    You could remember the parent, but that'd lead to a circular
    reference (not such a bad thing for 2.x).
    right. This gets pretty messy too, as you are forced to use instances,
    while I was trying to avoid that. In fact, I could have used modules
    instead of classes, but since python constrains me to one module per file,
    I tried to get away with something a bit finer grained.
    Perhaps if you give us C++ code of what you're trying to do, we
    can tell you why you don't need to do it ;)
    right. That's exactly what I want. Please show me the right idiom to use
    in python to solve the above problem.

    And by the way, the project I'm talking about is 'synopsis', at
    http://synopsis.sourceforge.net/, a modular source code inspection tool
    with parsers for IDL, C++, python, and a couple of output formatters.
    The module structure is this:

    Synopsis/
    Core/
    Util
    AST
    Type
    Parser/
    IDL
    C++
    Python
    Linker/
    Linker
    Formatter/
    HTML
    TexInfo
    DocBook
    Dot
    ASCII
    ...

    and each node in this tree has its own set of parameters.
    Online docs are at http://synopsis.sourceforge.net/docs/index.html

    Regards,
    Stefan
  • Bjorn Pettersen at Jun 18, 2001 at 11:40 pm

    From: Mats Wichmann [mailto:xyzmats at laplaza.org]

    On Mon, 18 Jun 2001 13:23:33 -0500, Stefan Seefeld
    wrote:
    gbreed at cix.compulink.co.uk wrote:
    What am I doing wrong ? The above is possibly a bit driven
    by my C++ programming style. What is the python way of doing
    this ?
    You can get that to work in C++? It looks strange to me, I'm
    sure you can't be trying to do what you think you're trying to
    do. This is the nearest I can think of that works:
    uh, what do *you* think that I'm trying to do, then ? :)

    What I'm arguing about is a matter of name resolution. I sure
    can open a scope 'A' in C++, insert a new scope 'B' into it,
    and from within that access other symbols declared in scope 'A'.
    In fact, I don't need to qualify them (i.e. 'foo' instead of 'A::foo'
    for any symbol 'foo' in the scope 'A' is just fine) if I'm inside
    that scope, no matter how deeply nested (of course, as long as there
    are no ambiguities).
    Java and C++ are compiled. The class definition is instructions to
    the compiler, and can be self-referential, because the /reference/ is
    not going to happen until the class is loaded - no inconsistency. Not
    so for Python, the class definition is code that is actually run to
    build the class object, and before that object has been built, there's
    nothing to refer to yet, as Alex said.
    But that's an implementation detail only, since it works perfectly for
    functions:

    def foo():
    foo()

    insert-definition-of-letrec-vs-let-here'ly y'rs
    -- bjorn
  • Skip Montanaro at Jun 19, 2001 at 12:21 am
    Bjorn> But that's an implementation detail only, since it works
    Bjorn> perfectly for functions:

    Bjorn> def foo():
    Bjorn> foo()

    Only because at the point that foo calls itself recursively, the definition
    of foo is in the module's global symbol table, assuming foo is def'd at the
    module scope. If foo is nested inside another function, it can't call
    itself directly without some help from the function it's enclosed in.

    Before nested scopes, the following won't work:

    % python
    Python 2.1.1a1 (#10, Jun 8 2001, 14:37:03)
    [GCC 2.96 20000731 (Linux-Mandrake 8.0 2.96-0.48mdk)] on linux2
    Type "copyright", "credits" or "license" for more information.
    if 1:
    ... def bar():
    ... def foo(i=0):
    ... if i < 10:
    ... foo(i+1)
    ... foo()
    ... bar()
    ...
    <stdin>:2: SyntaxWarning: local name 'foo' in 'bar' shadows use of 'foo' as global in nested scope 'foo'
    Traceback (most recent call last):
    File "<stdin>", line 7, in ?
    File "<stdin>", line 6, in bar
    File "<stdin>", line 5, in foo
    NameError: global name 'foo' is not defined
    from __future__ import nested_scopes
    if 1:
    ... def bar():
    ... def foo(i=0):
    ... if i < 10:
    ... foo(i+1)
    ... foo()
    ... bar()
    ...
    >>>

    When defining a class, the code within the class's scope is executed
    immediately, before a class object has been bound to the class's name.

    --
    Skip Montanaro (skip at pobox.com)
    (847)971-7098
  • Greg Ewing at Jun 20, 2001 at 4:12 am

    Skip Montanaro wrote:
    When defining a class, the code within the class's scope is executed
    immediately, before a class object has been bound to the class's name.
    But it *could* be done differently. An empty class
    object could be created, bound to the name, and then
    methods added to it. This would be analogous to what
    is done with modules.

    --
    Greg Ewing, Computer Science Dept, University of Canterbury,
    Christchurch, New Zealand
    To get my email address, please visit my web page:
    http://www.cosc.canterbury.ac.nz/~greg
  • Remco Gerlich at Jun 19, 2001 at 10:27 am

    Bjorn Pettersen <BPettersen at NAREX.com> wrote in comp.lang.python:
    From: Mats Wichmann [mailto:xyzmats at laplaza.org]
    Java and C++ are compiled. The class definition is instructions to
    the compiler, and can be self-referential, because the /reference/ is
    not going to happen until the class is loaded - no inconsistency. Not
    so for Python, the class definition is code that is actually run to
    build the class object, and before that object has been built, there's
    nothing to refer to yet, as Alex said.
    But that's an implementation detail only, since it works perfectly for
    functions:

    def foo():
    foo()
    The difference is that a class is executed when it's defined, and a function
    is executed when it is called. By the time the function is called, 'foo'
    exists, of course.

    --
    Remco Gerlich
  • Bjorn Pettersen at Jun 19, 2001 at 3:45 pm

    From: Skip Montanaro [mailto:skip at pobox.com]

    Bjorn> But that's an implementation detail only, since it works
    Bjorn> perfectly for functions:

    Bjorn> def foo():
    Bjorn> foo()

    Only because at the point that foo calls itself recursively,
    the definition
    of foo is in the module's global symbol table, assuming foo
    is def'd at the
    module scope. If foo is nested inside another function, it can't call
    itself directly without some help from the function it's enclosed in.
    And since this was/is changed with the latest implementation, it is an
    implementation detail.. no?

    [snip example]
    When defining a class, the code within the class's scope is executed
    immediately, before a class object has been bound to the class's name.
    Which is the implementation detail. You could easily envision an
    implementation that first binds the class name to a skeleton class
    object that only contains enough information for the class to be
    self-referential. Other languages do this, so it's perfectly possible.
    I'm not going to argue whether it's a good idea in Python or not <wink>.

    -- bjorn

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
grouppython-list @
categoriespython
postedJun 18, '01 at 4:05p
activeJun 21, '01 at 5:00p
posts15
users10
websitepython.org

People

Translate

site design / logo © 2022 Grokbase