Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
313 views
in Technique[技术] by (71.8m points)

python 2.7 - Access base class attribute in derived class - in "class scope"

class Outer(object):
    class InnerBase(object): _var = {'foo', 'bar'}
    class Derived(InnerBase):
        _var = _var | {'baz'} # NameError: name '_var' is not defined
        _var = InnerBase._var | {'baz'} #  name 'InnerBase' is not defined
        _var = Outer.InnerBase._var | {'baz'} #  free variable 'Outer'
        # referenced before assignment in enclosing scope

Moving _var in Outer does not help - moving it in module scope would work but defeats the purpose of having classes. So how to go about that ?

EDIT: coming from Java so the scoping rules of classes are a head scratcher for me - a briefing would be appreciated. This works btw:

    class Derived(InnerBase): pass
    Derived._var = InnerBase._var | {'baz'}

but it's not the pinnacle of elegance.

Related: Nested classes' scope? - but here we specifically want to access our parent class (rather than the Outer type)

EDIT2: What I am actually after is a _var = __class__._var-like syntax (or hack), or an explanation as to why it's not there

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Python never searches for a name in enclosing class statements. Mark Lutz uses the acronym LEGB to summarize scope in his introduction to Python (Learning Python): Python searches the local scope, then the local scope of any enclosing def statements, then the global scope, and finally the built-in scope. Class statements are excluded from this scope list; Python does not search enclosing class statements for a name.

One solution is to un-nest your classes. In Python, using un-nested classes is often preferred for its simplicity. But, of course, there are good reasons to nest classes as well. Why have you nested InnerBase? I wonder if you might have nested that class because of your experience in Java. Would the following work for you just as well?

class InnerBase(object):
    _var = {'foo', 'bar'}

class Derived(InnerBase):
    _var = InnerBase._var | {'baz'}

>>> Derived._var
set(['baz', 'foo', 'bar'])

The moment you nest these two class statements under another class statement they will be excluded from name searches, since they have become part of the larger class statement and are thus excluded from the searching of the various scopes.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...