Thursday, January 16, 2014

Python code indentation nightmare

After numerous hesitations, overcoming my intuitive distaste of Python as programming language, I finally decided to learn it. This is not just for getting familiar with the core coolness of Python and getting myself into Python mainstream, but more for not finding myself becoming a Java-mastodon (a-la COBOL-mastodon or FORTRAN-mastodon) in the next 10 years. So, I created a little project, and started to push lines of code into it.

My first experience with Python has not changed anything about my bad attitude towards Python syntax:
  • Code structures simply don't look fine without opening and closing curly braces, everything looks like a big unstructured mess.
  • Doc-strings written as a comment in the body(!), where I can write any crap I want simply don't feel like an API documentation to a class/method/function.
  • """, which can be used either as a multi-line comment separator or ... as a multi-line string separator when assigned to a variable. Isn't it weird? One of my university professors used to say: "If you wan't to confuse a man, either call two different things with the same name, or call two equal things with different names", and I totally agree with him.
  • Two forms: "import thing" and "from thing import another_thing". Why do I need both of them? Why can't I just use: "import thing.another_thing" or "import thing [another_thing]" like in Perl?
  • Indentation...

Indentation worth another post. I've spent about an hour trying to understand why Unit test, which I added to a forked project's test suite doesn't run:

class TestSchemes(TestCase):
    ...
    def test_find(self):
        work = Scheme.find('wlan0', 'work')
        assert work.options['wpa-ssid'] == 'workwifi'

 # Added my test:
 def test_mytest(self):
  work = Scheme.find('wlan0', 'work')
  work.delete()
  work = Scheme.find('wlan0', 'work')
  assert work == None

Trying to run - my test doesn't run, and there's no single error. I thought, may be test methods are registered somewhere (unlikely, but who knows..), but this wasn't the case. Maybe test_mytest is some registered name in Python? Tried another method names, but with no luck. Finally, I tried one more thing: copied and pasted one of the existing method's declarations using Vim's 'yy' and 'p' shortcuts, then renamed the pasted method name, and voila! That worked! Hm... What's the difference between:

    def test_mytest(self):
        work = Scheme.find('wlan0', 'work')
        work.delete()
        work = Scheme.find('wlan0', 'work')
        assert work == None

and:

 def test_mytest(self):
  work = Scheme.find('wlan0', 'work')
  work.delete()
  work = Scheme.find('wlan0', 'work')
  assert work == None

Right.. this is white-space against tab. I always indent my code using tabs, so the method I added was also indented using tabs. As it turns out, the original code was indented using spaces, so the new method simply wasn't recognized until I replaced all tabs with spaces. This is really really weird situation, when indentation characters have an effect on execution flow. Don't you agree?

To complete, I'd like to write a couple of warm words about Python. There are plenty of frameworks and libraries written in Python. GitHub is teeming with lots and lots of interesting and fun projects, from which you can learn. If you want to build a fast prototype, it's awesome. Not as awesome as Java + Maven, but still :-) I'm mastodon...

May the source be with you.

7 comments:

Moránar said...

You make interesting points, about import for example, but "This is really really weird situation" about spacing is not one of them. It's not weird, it's one of the first things mentioned in every Python manual and tutorial: spacing is important, and tabs aren't the same thing as spaces. Usually, some kind of advice about working with a modern text editor / IDE follow that.

Acting surprised about this in 2014 kind of detracts from the rest of your points.

Michael said...

You're right, this is described in every tutorial, but I didn't start from one. Forgive me, but "white-spaces vs tabs" mess in Python really looks at least strange, in my opinion. What I wanted is just open a file in Vim editor, and add some functionality, why should I bother myself with installing special IDE?

As for the 2014, it's too late, I agree, but it's better late than never, right? :)

Hartmut said...

Extra "fun" point for being used to pressing TAB taking care of proper indentation for you in Emacs c-mode / php-mode ...

This, the lack of switch/case and the 2.x -> 3.0 growing pains keep me from looking into it any further for now. Maybe once again once the 3.0 migration pains are eventually over ...

Unknown said...

Did you tried to learn Groovy? I think you will find a better world there.

Unknown said...

I think some clarification is needed.

1. "Code structures simply don't look fine..." it is just your personal opinion. To me "curly braces" madness "doesn't look fine". But I don't write rant on my blog, instead I just changed language. And if you worry about tabs vs. spaces you should probably configure you editor to do the hard work for you. Vim is quite good at it.

2a. "Doc-strings written as a comment in the body(!)" - the place where you put your comments is kinda unusual. But hey - Python has built-in support for documentation! :-)

2b. "where I can write any crap" - yeah, like putting documentation in comments before class doesn`t allow you to put a crap in it...
What you will find in in doc-strings depends only person that writes those. In PHP you can follow phpDoc / Doxygen / you name it convention and in Python world Sphinx rules are the one you should obey to.

3a. " """, which can be used either as a multi-line comment separator or ... as a multi-line string separator when assigned to a variable. Isn't it weird? "
In PHP you can put miltiline comment usin either /* ... */ syntax or heredoc << 3.x transition madness. And this is just one of the big issues of Python. But this is similar to PHP's inconsistancy with functions arguments order. If you don`t find yourself confortable working with a language - don`t struggle. There are many great languages out there. However if you judge language only by some really minor things without taking a deep dive you would have hard time to find a language suitable for you.

Best regards

Michał Bachowski

Michael said...

Michal, blog is exactly the place to express one's "personal opinion".
And one of my personal (also professional) opinions is such that I must be able to write code anywhere, including the unconfigured option of notepad.exe, and the code (either compiled or not) must run.

Unknown said...

Yes Michael you said it,I had worked in almost all languages,Python is a very good programming language,the only thing i didn't liked is the indentation and with out curly braces.