Re: Creating a local variable scope.

Discussion in 'Python' started by markolopa, Nov 29, 2009.

  1. markolopa

    markolopa Guest

    Hi,

    On 18 Sep, 10:36, "" <> wrote:
    > On Sep 11, 7:36 pm, Johan Grönqvist <> wrote:
    > > I find several places in my code where I would like tohavea variable
    > > scope that is smaller than the enclosing function/class/module definition.

    >
    > This is one of the single major frustrations I have with Python and an
    > important source of bugs for me. Here is a typical situation


    Here is another bug that I just got. Twenty minutes lost to find it...

    class ValueColumn(AbstractColumn):
    def __init__(self, name, header, domain_names):
    if type(domain_names) != tuple:
    raise ValueError('a tuple of domain names must be given')
    for name in domain_names:
    if type(name) != str:
    raise ValueError('a tuple of domain names must be
    given')
    self.domain_names = domain_names
    super(ValueColumn, self).__init__(name, header)

    The upper class was initialized with the wrong name, because the for
    loop to check
    domain_names used "name" which is also the argument to be passed.

    If is an old thread but I am reopening to present real situation where
    this Python
    "feature" bothers me...

    Marko
     
    markolopa, Nov 29, 2009
    #1
    1. Advertising

  2. markolopa

    Lie Ryan Guest

    On 11/30/2009 8:12 AM, markolopa wrote:
    > Hi,
    >
    > On 18 Sep, 10:36, ""<> wrote:
    >> On Sep 11, 7:36 pm, Johan Grönqvist<> wrote:
    >>> I find several places in my code where I would like tohavea variable
    >>> scope that is smaller than the enclosing function/class/module definition.

    >>
    >> This is one of the single major frustrations I have with Python and an
    >> important source of bugs for me. Here is a typical situation

    >
    > Here is another bug that I just got. Twenty minutes lost to find it...
    >
    > class ValueColumn(AbstractColumn):
    > def __init__(self, name, header, domain_names):
    > if type(domain_names) != tuple:
    > raise ValueError('a tuple of domain names must be given')
    > for name in domain_names:
    > if type(name) != str:
    > raise ValueError('a tuple of domain names must be
    > given')
    > self.domain_names = domain_names
    > super(ValueColumn, self).__init__(name, header)
    >
    > The upper class was initialized with the wrong name, because the for
    > loop to check
    > domain_names used "name" which is also the argument to be passed.
    >
    > If is an old thread but I am reopening to present real situation where
    > this Python
    > "feature" bothers me...
    >


    here is another bug you might have if python have an "even-more-local"
    scope:

    while True:
    s = raw_input("enter something: ")
    if s not in ('q', 'quit', 'exit'): break
    print s

    if the while block has become its own namespace; print s would generate
    NameError.

    It is one or the other, you will have problem caused by "namespace too
    small" or "namespace too big". Neither is better than the other, so
    python's two-level name resolution (global and local level) is the
    simplest one, is the better one.
     
    Lie Ryan, Nov 29, 2009
    #2
    1. Advertising

  3. markolopa

    markolopa Guest

    Hi Lie!

    On Nov 29, 11:11 pm, Lie Ryan <> wrote:
    > here is another bug you might have if python have an "even-more-local"
    > scope:
    >
    > while True:
    >      s = raw_input("enter something: ")
    >      if s not in ('q', 'quit', 'exit'): break
    > print s
    >
    > if the while block has become its own namespace; print s would generate
    > NameError.


    This bug you show is completely different, because it is not
    dangerous: you get the error and you realise directly how to fix it.

    > It is one or the other, you will have problem caused by "namespace too
    > small" or "namespace too big". Neither is better than the other, so
    > python's two-level name resolution (global and local level) is the
    > simplest one, is the better one.


    I would be much happier with the smaller namespace. To fix the code
    that you show I would impose

    s = None
    while True:
    s = raw_input("enter something: ")
    if s not in ('q', 'quit', 'exit'): break
    print s

    The use in a block of variables created in an inner block is (for me
    at least) more an exception than a rule.

    Less than 3 hours have passed since my last post and got yet another
    bug that could be prevented if Python had the functionality that other
    languages have to destroy variables when a block ends. Here is the
    code:

    =========

    arg_columns = []
    for domain in self.domains:
    i = self.get_column_index(column_names, domain.name)
    col = column_elements
    if len(col) != len(val_column):
    ValueError('column %s has not the same size as the value
    column %s'
    % (column_names, self.name))
    arg_columns.append(col)

    [...]

    value_dict = {}
    for i, val_str in enumerate(val_column):
    arg_name_row = [c for c in arg_columns]
    args = [domain[name] for name in arg_name_row]
    value_dict[tuple(args)] = float(val_str)
    repo[self.name] = value_dict

    =========

    The bug is corrected replacing the line

    args = [domain[name] for name in arg_name_row]

    by

    args = [domain[name] for name, domain in zip(arg_name_row,
    self.domains)]

    so "domain" should not exist in my namespace since I have no
    information associated to "domain" only to "self.domains". Python
    should allow me to write safe code!

    Antoher 15 minutes lost because of that Python "feature"... Is it only
    me???

    Thanks for your comment!
    Marko
     
    markolopa, Nov 30, 2009
    #3
  4. markolopa

    Steve Howell Guest

    On Nov 29, 4:26 pm, markolopa <> wrote:
    > Less than 3 hours have passed since my last post and got yet another
    > bug that could be prevented if Python had the functionality that other
    > languages have to destroy variables when a block ends. Here is the
    > code:
    >
    > =========
    >
    > arg_columns = []
    > for domain in self.domains:
    >     i = self.get_column_index(column_names, domain.name)
    >     col = column_elements
    >     if len(col) != len(val_column):
    >         ValueError('column %s has not the same size as the value
    > column %s'
    >                    % (column_names, self.name))
    >         arg_columns.append(col)
    >
    > [...]
    >
    > value_dict = {}
    > for i, val_str in enumerate(val_column):
    >     arg_name_row = [c for c in arg_columns]
    >     args = [domain[name] for name in arg_name_row]
    >     value_dict[tuple(args)] = float(val_str)
    > repo[self.name] = value_dict
    >
    > =========
    >
    > The bug is corrected replacing the line
    >
    >     args = [domain[name] for name in arg_name_row]
    >
    > by
    >
    >     args = [domain[name] for name, domain in zip(arg_name_row,
    > self.domains)]
    >
    > so "domain" should not exist in my namespace since I have no
    > information associated to "domain" only to "self.domains". Python
    > should allow me to write safe code!
    >
    > Antoher 15 minutes lost because of that Python "feature"... Is it only
    > me???
    >


    I occasionally make the error you make, but I think the real problem
    you are having is lack of attention to detail. If name collisions are
    a common problem for you, consider writing shorter methods or develop
    the habit of using more descriptive variable names. In the code
    above, you could have easily cleaned up the namespace by extracting a
    method called get_arg_columns(). Having to spend 15 minutes tracking
    down a bug usually indicates that you are not being systematic in your
    thinking. If you are rushing too much, slow down. If you are tired,
    take a break. If you make the same mistake twice, commit to yourself
    not to make it a third time. Also, test your methods one at a time
    and get them rock solid before writing more code.
     
    Steve Howell, Nov 30, 2009
    #4
  5. * markolopa:
    >
    > On 18 Sep, 10:36, "" <> wrote:
    >> On Sep 11, 7:36 pm, Johan Grönqvist <> wrote:
    >>> I find several places in my code where I would like tohavea variable
    >>> scope that is smaller than the enclosing function/class/module definition.

    >> This is one of the single major frustrations I have with Python and an
    >> important source of bugs for me. Here is a typical situation

    >
    > Here is another bug that I just got. Twenty minutes lost to find it...
    >
    > class ValueColumn(AbstractColumn):
    > def __init__(self, name, header, domain_names):
    > if type(domain_names) != tuple:
    > raise ValueError('a tuple of domain names must be given')
    > for name in domain_names:
    > if type(name) != str:
    > raise ValueError('a tuple of domain names must be
    > given')
    > self.domain_names = domain_names
    > super(ValueColumn, self).__init__(name, header)
    >
    > The upper class was initialized with the wrong name, because the for
    > loop to check
    > domain_names used "name" which is also the argument to be passed.
    >
    > If is an old thread but I am reopening to present real situation where
    > this Python
    > "feature" bothers me...


    I think if one could somehow declare names as const (final, readonly, whatever)
    then that would cover the above plus much more.


    Cheers,

    - Alf
     
    Alf P. Steinbach, Nov 30, 2009
    #5
  6. markolopa

    Dave Angel Guest

    markolopa wrote:
    > <snip>
    > =======
    >
    > arg_columns =]
    > for domain in self.domains:
    > i =elf.get_column_index(column_names, domain.name)
    > col =olumn_elements
    > if len(col) !=en(val_column):
    > ValueError('column %s has not the same size as the value
    > column %s'
    > % (column_names, self.name))
    > arg_columns.append(col)
    >
    > [...]
    >
    > value_dict =}
    > for i, val_str in enumerate(val_column):
    > arg_name_row =c for c in arg_columns]
    > args =domain[name] for name in arg_name_row]
    > value_dict[tuple(args)] =loat(val_str)
    > repo[self.name] =alue_dict
    >
    > =======
    >
    > The bug is corrected replacing the line
    >
    > args =domain[name] for name in arg_name_row]
    >
    > by
    >
    > args =domain[name] for name, domain in zip(arg_name_row,
    > self.domains)]
    >
    > so "domain" should not exist in my namespace since I have no
    > information associated to "domain" only to "self.domains". Python
    > should allow me to write safe code!
    >
    > Antoher 15 minutes lost because of that Python "feature"... Is it only
    > me???
    >
    >

    Yep, I think so. You're proposing a much more complex scoping rule,
    where if a variable already exists before entering a loop, then the loop
    uses that existing variable, but if not, it creates its own local one
    and destroys it when exiting the loop. That's the exact opposite of
    what function definitions do, which already makes it confusing.

    I think if you had your wish, you'd find that you had more exceptions
    where you had to pre-declare things, than the times when you avoided the
    bugs you describe. I don't like languages that make me write extra
    stuff 100 times, to save one instance of extra debugging. If Python
    already required declarations, then I might buy your arguments. But it
    wouldn't be Python.
    > Thanks for your comment!
    > Marko
    >
    >


    In your particular case, the compiler couldn't guess whether you used
    the first loop to decide which domain to use in the second loop, or
    whether you accidentally reused the same name without giving it a new
    value in the new loop. If you need to use the same name, you could
    always follow your loops with the del statement to invalidate the name.


    DaveA
     
    Dave Angel, Nov 30, 2009
    #6
  7. markolopa

    Terry Reedy Guest

    markolopa wrote:

    >
    > so "domain" should not exist in my namespace since I have no
    > information associated to "domain" only to "self.domains". Python
    > should allow me to write safe code!


    Leaving iteration names bound after loop exit is a feature. If you do
    not like it, explicitly unbind it.
     
    Terry Reedy, Nov 30, 2009
    #7
  8. markolopa

    markolopa Guest

    Hi Steve!

    On Nov 30, 1:46 am, Steve Howell <> wrote:
    > I occasionally make the error you make, but I think the real problem
    > you are having is lack of attention to detail.  If name collisions are
    > a common problem for you, consider writing shorter methods


    Yes, this could be a solution, though I believe that too many (sub)
    methods called by a single method turn the code less readable.

    > or develop
    > the habit of using more descriptive variable names.


    Also a good suggestion. Alternatively I have considered to do the
    opposite, to use weird (the opposite of descriptive) names for
    variables that should exist only inside the block, in order to
    differentiate them from the variables that should persist.

    >  In the code
    > above, you could have easily cleaned up the namespace by extracting a
    > method called get_arg_columns().  Having to spend 15 minutes tracking
    > down a bug usually indicates that you are not being systematic in your
    > thinking.  If you are rushing too much, slow down.  If you are tired,
    > take a break.  If you make the same mistake twice, commit to yourself
    > not to make it a third time.  Also, test your methods one at a time
    > and get them rock solid before writing more code.


    Nice suggestions thanks, all of them apply to me!...:) Compared to
    the normal coder I have a strong tendency to loose myself in details.
    That is why I have to be very systematic, write lots of defensive code
    (to catch the bugs as soon as possible), write unit tests (great habit
    I've developped recently!). Python is fantastic for those goals. The
    only laking feature I find is really the survival of variables, a
    problem that does not exist in C++ or in Perl (with use strict).
    Besides this kind of bug I have noticed only 2 other sources of bug I
    had more than once with python code.
    - expecting float from integer division (easily avoidable, either with
    3.0 or from __future__...)
    - expecting diferent objects in a list have having the same several
    times (deepcopy issue, also easily avoidable once we know it)

    So my only other problem is with this "survival" feature. I consider
    to write my own version of Python, the one that would not allow the
    usage of varaibles outside the block it was created. Of course I won't
    rewrite CPython but I could add an error (or warning) to pylint. With
    some luck it already exists, I will investigate...

    Greets!
    Marko
     
    markolopa, Nov 30, 2009
    #8
  9. markolopa

    markolopa Guest

    On Nov 30, 4:46 am, Dave Angel <> wrote:
    > markolopa wrote:
    > > Antoher 15 minutes lost because of that Python "feature"... Is it only
    > > me???

    >
    > Yep, I think so.


    Not very consoling but thanks anyway!...:))))

    > You're proposing a much more complex scoping rule,
    > where if a variable already exists before entering a loop, then the loop
    > uses that existing variable, but if not, it creates its own local one
    > and destroys it when exiting the loop.


    Alternatively you could forbid the creation of a variable in a inner
    block if it already exists. Either that or forbid the usage of the
    variable in an outter block later if it exists both in an inner and
    outer block.

    Aren't there languages that forbid the declarations of variables in a
    function with the same name as global variables? I know that this is
    an extreme defensive measure, but I have to say that I like it.
    Allowing to create a new variable when a variable with the same name
    is already exists in the namespace makes for harm that good, for me at
    least. Of course this issue is much broader than the one I proposed
    initially.

    > I think if you had your wish, you'd find that you had more exceptions
    > where you had to pre-declare things, than the times when you avoided the
    > bugs you describe.  


    You are probably right, otherwise Guido would have done what I
    suggest... but I really don't see why.

    > I don't like languages that make me write extra
    > stuff 100 times, to save one instance of extra debugging.  If Python
    > already required declarations, then I might buy your arguments.  But it
    > wouldn't be Python.


    My guess is that if the change I propose was implemented, the number
    additional lines that would be needed to make the present python code
    work would be 1 in a thousand or less. Of course I may be wrong...
    Besides this additional line can make the code more readable,
    strassing the fact that the variable inside the block actually
    "belongs" to outside.

    > In your particular case, the compiler couldn't guess whether you used
    > the first loop to decide which domain to use in the second loop,


    That is what I wish the compiler should forbid...:->

    > or
    > whether you accidentally reused the same name without giving it a new
    > value in the new loop.  


    That is what I do regularly...8->

    > If you need to use the same name, you could
    > always follow your loops with the del statement to invalidate the name.


    Several people have suggested explicit destruction of the variables I
    don't need. Python allows it but of course this does not solve my
    problem. It does not make sense to use such a clean language as Python
    and regularly delete all variables used inside the blocks when leaving
    it. And of course the bug comes because I have no idea that I am using
    the same name again.

    Cheers!
    Marko
     
    markolopa, Nov 30, 2009
    #9
  10. markolopa

    Lie Ryan Guest

    On 11/30/2009 8:13 PM, markolopa wrote:
    > On Nov 30, 4:46 am, Dave Angel<> wrote:
    >> markolopa wrote:
    >>> Antoher 15 minutes lost because of that Python "feature"... Is it only
    >>> me???

    >>
    >> Yep, I think so.

    >
    > Not very consoling but thanks anyway!...:))))
    >
    >> You're proposing a much more complex scoping rule,
    >> where if a variable already exists before entering a loop, then the loop
    >> uses that existing variable, but if not, it creates its own local one
    >> and destroys it when exiting the loop.

    >
    > Alternatively you could forbid the creation of a variable in a inner
    > block if it already exists. Either that or forbid the usage of the
    > variable in an outter block later if it exists both in an inner and
    > outer block.
    >


    Of course, the best solution would be to allow assignment only in a
    single line of source of code. Reassignment by different lines of code
    would be a syntax error. You're forced to have different names if you
    want assign something multiple times. That way, no bugs is possible.
     
    Lie Ryan, Nov 30, 2009
    #10
  11. On Mon, 30 Nov 2009 02:11:12 +0100, Alf P. Steinbach wrote:

    > I think if one could somehow declare names as const (final, readonly,
    > whatever) then that would cover the above plus much more.


    Having real constants is one feature that I miss. Because Python doesn't
    have constants, I find I've lost the discipline to avoid "magic
    numbers" (and strings) in my code.


    --
    Steven
     
    Steven D'Aprano, Nov 30, 2009
    #11
  12. markolopa

    Dave Angel Guest

    markolopa wrote:
    > On Nov 30, 4:46 am, Dave Angel <> wrote:
    >
    >> markolopa wrote:
    >>
    >>> Antoher 15 minutes lost because of that Python "feature"... Is it only
    >>> me???
    >>>

    >> Yep, I think so.
    >>

    >
    > Not very consoling but thanks anyway!...:))))
    >
    >
    >> You're proposing a much more complex scoping rule,
    >> where if a variable already exists before entering a loop, then the loop
    >> uses that existing variable, but if not, it creates its own local one
    >> and destroys it when exiting the loop.
    >>

    >
    > Alternatively you could forbid the creation of a variable in a inner
    > block if it already exists.

    Somehow you seem to think there's some syntax for "creating" a
    variable. In fact, what's happening is you're binding/rebinding a name
    to an object. And if you forbid doing this inside the loop, for names
    that exist outside the loop, then most of the useful work the loop does
    becomes impossible. Remember, in Python, there's no declaration of a
    variable (except the global statement, which does it sort-of). So you'd
    be disallowing the following:

    counter = 5
    for item in itemlist:
    if item > 19:
    counter = counter + 5

    The only way I can think you possibly want this is if you're just
    referring to "loop variables", such as "item" in the above example. The
    problem is that on many loops, for example a "while" loop, there's no
    such thing.

    > Either that or forbid the usage of the
    > variable in an outter block later if it exists both in an inner and
    > outer block.
    >
    >

    You need to define "exists" in order to make discussion unambiguous.
    Without extra declarations of some type, I can't believe there's any way
    to make any variation of this concept work in the general case.
    > Aren't there languages that forbid the declarations of variables in a
    > function with the same name as global variables? I know that this is
    > an extreme defensive measure, but I have to say that I like it.
    > Allowing to create a new variable when a variable with the same name
    > is already exists in the namespace makes for harm that good, for me at
    > least. Of course this issue is much broader than the one I proposed
    > initially.
    >
    >

    I can't think of any, among the 35 languages I've programmed in
    professionally over the years. All right, to be fair, about half of
    those were assembly languages at various levels. And I don't believe I
    worked in any assembly language that even had separate scoping for
    functions.

    DaveA
     
    Dave Angel, Nov 30, 2009
    #12
  13. Steven D'Aprano wrote:
    > On Mon, 30 Nov 2009 02:11:12 +0100, Alf P. Steinbach wrote:
    >
    >
    >> I think if one could somehow declare names as const (final, readonly,
    >> whatever) then that would cover the above plus much more.
    >>

    >
    > Having real constants is one feature that I miss. Because Python doesn't
    > have constants, I find I've lost the discipline to avoid "magic
    > numbers" (and strings) in my code.
    >
    >
    >

    I don't get you, this can be easily avoid with a strong naming
    convention. I mean, despite they are not really constants, you can still
    use variables to name your numbers and string, to give the reader a
    usefull hint on the meaning of your code. Yet it is still a matter of
    discipline, it is sometimes very tempting to put the string directly
    (unlike numbers string can be meaningful sometimes)

    JM
     
    Jean-Michel Pichavant, Nov 30, 2009
    #13
  14. * Jean-Michel Pichavant:
    > Steven D'Aprano wrote:
    >> On Mon, 30 Nov 2009 02:11:12 +0100, Alf P. Steinbach wrote:
    >>
    >>
    >>> I think if one could somehow declare names as const (final, readonly,
    >>> whatever) then that would cover the above plus much more.
    >>>

    >>
    >> Having real constants is one feature that I miss. Because Python
    >> doesn't have constants, I find I've lost the discipline to avoid
    >> "magic numbers" (and strings) in my code.
    >>
    >>
    >>

    > I don't get you, this can be easily avoid with a strong naming
    > convention. I mean, despite they are not really constants, you can still
    > use variables to name your numbers and string, to give the reader a
    > usefull hint on the meaning of your code. Yet it is still a matter of
    > discipline, it is sometimes very tempting to put the string directly
    > (unlike numbers string can be meaningful sometimes)


    It may be surprising how many things turn out to be readonly.

    Consider the OP's code:


    <code>
    class ValueColumn(AbstractColumn):
    def __init__(self, name, header, domain_names):
    if type(domain_names) != tuple:
    raise ValueError('a tuple of domain names must be given')
    for name in domain_names:
    if type(name) != str:
    raise ValueError('a tuple of domain names must be given')
    self.domain_names = domain_names
    super(ValueColumn, self).__init__(name, header)
    </code>


    Here the arguments should ideally be read only names, which would have cought
    the bug of reusing 'name' in the for loop.

    But you really wouldn't code this as


    <code>
    class ValueColumn(AbstractColumn):
    def __init__(SELF, NAME, HEADER, DOMAIN_NAMES):
    if type(DOMAIN_NAMES) != tuple:
    raise ValueError('a tuple of domain names must be given')
    for name in DOMAIN_NAMES:
    # Argh, at this point 'name' is readonly, but cannot express that.
    if type(name) != str:
    raise ValueError('a tuple of domain names must be given')
    SELF.domain_names = domain_names
    super(ValueColumn, SELF).__init__(NAME, HEADER)
    </code>


    Or, at least I wouldn't do that.

    It's ugly.

    And you have to /change the names/ as the readonly-ness changes.


    Cheers,

    - Alf
     
    Alf P. Steinbach, Nov 30, 2009
    #14
  15. markolopa

    r0g Guest

    markolopa wrote:
    > On Nov 30, 4:46 am, Dave Angel <> wrote:
    >> markolopa wrote:

    <snip>
    >> or
    >> whether you accidentally reused the same name without giving it a new
    >> value in the new loop.

    >
    > That is what I do regularly...8->
    >




    Well really dude, you need to stop doing that. It's not a language
    problem, it's a memory problem (human not RAM!). You need to be aware of
    what you're putting into your namespace. This is one of the reasons
    people try to avoid using global variables, if you forget you've used a
    variable name and use it again somewhere you get an undefined state and
    hours of debugging / data loss / subtle corruptions you won't spot until
    the backups have all been cycled etc.

    I'm surprised you have a recurring problem with this really. My memory
    is terrible and I reuse variable names all over the place without any
    trouble. Maybe try keeping the length of your functions down so that
    they fit on a single screen and create and use a strong naming
    convention i.e.

    Long, descriptive variable names all_in_lower_case
    Function names all in CamelCase
    Global names are in ALL CAPS
    Loop variable names all prefixed with 'each_'

    The details don't so much matter as long as you are consistent with it.
    I'm sure many here would hate my coding conventions if they had to use
    them but they seem to work OK for me and I can't recall ever having this
    problem.


    Roger.
     
    r0g, Dec 1, 2009
    #15
  16. markolopa

    markolopa Guest

    Hi Dave,

    Since you feel like discussing my weird idea of Python reform :) lets
    go...

    On 30 Nov, 11:29, Dave Angel <> wrote:
    > Somehow you seem to think there's some syntax for "creating" avariable.  In fact, what's happening is you're binding/rebinding a name
    > to an object.  And if you forbid doing this inside the loop, for names
    > that exist outside the loop, then most of the useful work the loop does
    > becomes impossible.  Remember, in Python, there's no declaration of avariable(except the global statement, which does it sort-of).


    You are right, I have not used precise terms. Let's use examples then.

    > So you'd
    > be disallowing the following:
    >
    >     counter = 5
    >     for item in itemlist:
    >            if item > 19:
    >                 counter = counter + 5


    In this example, I would allow the expected behaviour. Since "counter"
    was bound in the outer loop, the new binding got in the inner loop
    would persist after the end of the "if" and the "for" block.

    Other examples:

    if True:
    a = 5
    print a

    would produce an error while

    a = 3
    if True:
    a = 5
    print a

    would print 5 (and not 3).

    But now I realise that one of my bugs wouldn't be solved, so I believe
    you have managed to convince me that my idea does not make much
    sense...:)

    > The only way I can think you possibly want this is if you're just
    > referring to "loop variables", such as "item" in the above example.  The
    > problem is that on many loops, for example a "while" loop, there's no
    > such thing.


    This would already be great. I believe that most bugs I've had related
    to this issue are due to accidental reuse of loop variables. But
    treating the loop variables as a special case is perhaps not very
    elegant.

    Greetings,
    Marko
     
    markolopa, Dec 1, 2009
    #16
  17. markolopa

    markolopa Guest

    Hi Roger,

    > > That is what I do regularly...8->

    >
    > Well really dude, you need to stop doing that. It's not a language
    > problem, it's a memory problem (human not RAM!).


    You guessed quite correctly!...:) I can't recognise my code sometimes
    after a single week. That's why I spend a lot of time cleaning it to
    be easy to get back. Fortunately it seems to be recognised as a good
    practice...

    > You need to be aware of
    > what you're putting into your namespace. This is one of the reasons
    > people try to avoid using global variables, if you forget you've used a variable name and use it again somewhere you get an undefined state and
    > hours of debugging / data loss / subtle corruptions you won't spot until
    >  the backups have all been cycled etc.


    Sure, zero global variables in my programs.

    > I'm surprised you have a recurring problem with this really. My memory
    > is terrible and I reuse variable names all over the place without any
    > trouble. Maybe try keeping the length of your functions down so that
    > they fit on a single screen and create and use a strong naming
    > convention i.e.
    >
    > Long, descriptive variable names all_in_lower_case
    > Function names all in CamelCase
    > Global names are in ALL CAPS


    yes, pep8 I guess.

    > Loop variable names all prefixed with 'each_'


    Interesting. A radical idea (and not very elegant for my taste I would
    say) but it could certainly make me avoid such bugs...

    Cheers!
    Marko
     
    markolopa, Dec 1, 2009
    #17
  18. markolopa

    r0g Guest

    Ben Finney wrote:
    > markolopa <> writes:
    >
    >> Hi Roger,
    >>

    > […]
    >>> Long, descriptive variable names all_in_lower_case
    >>> Function names all in CamelCase
    >>> Global names are in ALL CAPS

    >> yes, pep8 I guess.

    >
    > Not quite: it deviates from PEP 8 on function names, which should rather
    > be ‘lower_case_words_separated_by_underscores’.
    >
    > The ‘UPPER_CASE_WORDS_WITH_UNDERSCORES’ form is for “constantsâ€, i.e.
    > names that indicate they should stay bound to the same value through the
    > life of the program (which is the closest normal Python programs get to
    > a “constant†binding).
    >
    > The ‘TitleCase’ form should be used only for class names.
    >
    > The ‘camelCase’ form is not conformant with PEP 8 at all (which makes me
    > glad, since it's hideous).
    >



    Heh, see! It's a spiky subject ;) Someday I'm going to found a
    substantial open source project just so I can force subsequent
    contributors to format their code the way I like it! *bwahahahaaa* :)


    Roger.
     
    r0g, Dec 3, 2009
    #18
  19. markolopa

    Lie Ryan Guest

    On 12/2/2009 2:56 PM, Ben Finney wrote:
    > The ‘camelCase’ form is not conformant with PEP 8 at all (which makes me
    > glad, since it's hideous).


    For some reason, every time I look at a unittest code, I was thinking of
    Java... and not just because it's modeled after JUnitTest.
     
    Lie Ryan, Dec 3, 2009
    #19
  20. markolopa

    rwwh Guest

    On Nov 30, 1:26 am, markolopa <> wrote:

    > I would be much happier with the smaller namespace. To fix the code
    > that you show I would impose
    >
    > s = None
    > while True:
    >      s = raw_input("enter something: ")
    >      if s not in ('q', 'quit', 'exit'): break
    > print s


    So you propose: if the variable exists in a wider scope, you ideal
    python would not create it in an inner scope. How is this helping your
    original case?

    I remind you:

    class ValueColumn(AbstractColumn):
    def __init__(self, name, header, domain_names):
    if type(domain_names) != tuple:
    raise ValueError('blub')
    for name in domain_names:
    if type(name) != str:
    raise ValueError('blub')
    self.domain_names = domain_names
    super(ValueColumn, self).__init__(name, header)

    When "for name" is reached, "name" already exists and no local
    variable would be created. How does this help you?
     
    rwwh, Dec 10, 2009
    #20
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Hoi Wong
    Replies:
    8
    Views:
    1,123
    P. Lepin
    Feb 21, 2008
  2. Johan Grönqvist

    Creating a local variable scope.

    Johan Grönqvist, Sep 11, 2009, in forum: Python
    Replies:
    14
    Views:
    564
    Albert van der Horst
    Sep 24, 2009
  3. Manuel Graune

    Tracing variable scope (local vs. global)

    Manuel Graune, Dec 1, 2009, in forum: Python
    Replies:
    3
    Views:
    422
    Terry Reedy
    Dec 2, 2009
  4. David Filmer
    Replies:
    19
    Views:
    257
    Kevin Collins
    May 21, 2004
  5. Andrew Falanga
    Replies:
    2
    Views:
    205
    Andrew Falanga
    Nov 22, 2008
Loading...

Share This Page