python class variable not visible in __init__?

前端 未结 4 1243
孤街浪徒
孤街浪徒 2021-02-06 01:47

This code produces an error message, which I found surprising:

class Foo(object):
    custom = 1
    def __init__(self, custom=Foo.custom):
        self._custom          


        
相关标签:
4条回答
  • 2021-02-06 02:19

    I get the following error:

    Traceback (most recent call last):
      Line 1, in <module>
        class Foo(object):
      Line 3, in Foo
        def __init__(self, custom=Foo.custom):
    NameError: name 'Foo' is not defined
    

    This is because the name Foo is in the process of being defined as the __init__ function is defined, and is not fully available at that time.

    The solution is to avoid using the name Foo in the function definition (I also renamed the custom paramter to acustom to distinguish it from Foo.custom):

    class Foo(object):
        custom = 1
        def __init__(self, acustom=custom):
            self._custom = acustom
    x = Foo()
    print x._custom
    
    0 讨论(0)
  • 2021-02-06 02:22

    It's Foo that isn't visible, because you're in the middle of building it. But since you're in the same scope as custom, you can just say custom rather than Foo.custom:

    class Foo(object):
        custom = 1
        def __init__(self, mycustom=custom):
            self._custom = mycustom
    

    But note that changing Foo.custom later on won't affect the value of custom that subsequently-created Foos see:

    class Foo(object):
        custom = 1
        def __init__(self, mycustom=custom):
            self._custom = mycustom
    
    one = Foo()
    Foo.custom = 2
    two = Foo()
    print (two._custom)  # Prints 1
    

    By using a sentinel default value instead, you can get what you want:

    class Foo(object):
        custom = 1
        def __init__(self, mycustom=None):
            if mycustom is None:
                self._custom = Foo.custom
            else:
                self._custom = mycustom
    
    one = Foo()
    Foo.custom = 2
    two = Foo()
    print (two._custom)  # Prints 2
    
    0 讨论(0)
  • 2021-02-06 02:35

    What we do instead is the following

    class Foo( object ):
        custom = 1
        def __init__( self, arg=None )
            self._custom = self.custom if arg is None else arg
    

    This bypasses the confusing issue of whether or not the name Foo has been defined yet.

    0 讨论(0)
  • 2021-02-06 02:40

    The class body is executed before the class its self is defined, so default argument values can't reference the class. Just making custom the default (without class qualification) should work.

    0 讨论(0)
提交回复
热议问题