63

Much of my programming background is in Java, and I'm still doing most of my programming in Java. However, I'm starting to learn Python for some side projects at work, and I'd like to learn it as independent of my Java background as possible - i.e. I don't want to just program Java in Python. What are some things I should look out for?

A quick example - when looking through the Python tutorial, I came across the fact that defaulted mutable parameters of a function (such as a list) are persisted (remembered from call to call). This was counter-intuitive to me as a Java programmer and hard to get my head around. (See here and here if you don't understand the example.)

Someone also provided me with this list, which I found helpful, but short. Anyone have any other examples of how a Java programmer might tend to misuse Python...? Or things a Java programmer would falsely assume or have trouble understanding?

Edit: Ok, a brief overview of the reasons addressed by the article I linked to to prevent duplicates in the answers (as suggested by Bill the Lizard). (Please let me know if I make a mistake in phrasing, I've only just started with Python so I may not understand all the concepts fully. And a disclaimer - these are going to be very brief, so if you don't understand what it's getting at check out the link.)

  • A static method in Java does not translate to a Python classmethod
  • A switch statement in Java translates to a hash table in Python
  • Don't use XML
  • Getters and setters are evil (hey, I'm just quoting :) )
  • Code duplication is often a necessary evil in Java (e.g. method overloading), but not in Python

(And if you find this question at all interesting, check out the link anyway. :) It's quite good.)

Community
  • 1
  • 1
froadie
  • 79,995
  • 75
  • 166
  • 235
  • 2
    Good question. The article you linked to in the last paragraph is a very good start. You might consider pulling out a (very brief) summary of the bullet points given there, just so people don't duplicate the same list in the answers. (I nearly posted one of the points in the article.) – Bill the Lizard Feb 26 '10 at 03:59
  • @Bill the Lizard - updated, thanks for the suggestion. Just out of curiosity - which point were you going to post? :) – froadie Feb 26 '10 at 04:14
  • 1
    Also, please make this a Community Wiki. There's no "answer", just a lot of advice. – S.Lott Feb 26 '10 at 11:36
  • 1
    Related: http://stackoverflow.com/questions/954164/choosing-between-java-and-python – S.Lott Feb 26 '10 at 12:25
  • 1
    I was going to post "Getters and setters are evil." There is a night and day difference between the two languages on this point. They're probably the easiest way to spot someone who's just programming Java in Python. – Bill the Lizard Feb 26 '10 at 15:44
  • A sensation of [flying](http://xkcd.com/353/)? – Alex Miller Feb 26 '10 at 04:56

7 Answers7

25
  • Don't put everything into classes. Python's built-in list and dictionaries will take you far.
  • Don't worry about keeping one class per module. Divide modules by purpose, not by class.
  • Use inheritance for behavior, not interfaces. Don't create an "Animal" class for "Dog" and "Cat" to inherit from, just so you can have a generic "make_sound" method.

Just do this:

class Dog(object):
    def make_sound(self):
        return "woof!"

class Cat(object):
    def make_sound(self):
        return "meow!"

class LolCat(object):
    def make_sound(self):
        return "i can has cheezburger?"
Ryan Ginstrom
  • 13,915
  • 5
  • 45
  • 60
  • 6
    I know I might be missing something simple... but can you explain more the "why" behind your last point? – froadie Feb 26 '10 at 04:05
  • 4
    @froadie: It's not that having an Animal class is bad, it's just that it's completely unnecessary unless you want to provide a default implementation of make_sound(). – dsimcha Feb 26 '10 at 04:07
  • Hmmmm. But is polymorphism available in Python? Would that be a reason / justification...? (And I guess the next question is going to be - how much of this once you learn it should be bounced back to how you program Java? :) ) – froadie Feb 26 '10 at 04:15
  • 11
    Python uses the concept of "duck typing" (or in this case dog/cat typing :). If you pass an object to a method expecting it to have a certain interface, then as long as it has that interface you're fine. Inheritance has a lot of problems because of the extremely tight coupling, so only use it if you actually need it. – Ryan Ginstrom Feb 26 '10 at 04:34
  • 5
    @froadie: polymorphism is implicit in dynamic languages. inheritance just happens to be the easiest way to tell a static compiler that types are related. with dynamic languages and cheap exceptions its (mostly) unnecessary. – Javier Feb 26 '10 at 04:46
  • 3
    @froadie: None of what you learn in Python can be "bounced back" to Java. They're different languages. It's not just different syntax; the underlying concepts are different. The static declaration nature of Java makes it really different from Python. – S.Lott Feb 26 '10 at 11:52
  • IMO you should create classes for interfaces when: 1- you have a lot of children and want to maintain consistency of their respective methods, 2- for test mocking: it's easier to mock one parent class than x children – Flavian Hautbois Feb 24 '15 at 10:03
23

The referenced article has some good advice that can easily be misquoted and misunderstood. And some bad advice.

Leave Java behind. Start fresh. "do not trust your [Java-based] instincts". Saying things are "counter-intuitive" is a bad habit in any programming discipline. When learning a new language, start fresh, and drop your habits. Your intuition must be wrong.

Languages are different. Otherwise, they'd be the same language with different syntax, and there'd be simple translators. Because there are not simple translators, there's no simple mapping. That means that intuition is unhelpful and dangerous.

  • "A static method in Java does not translate to a Python classmethod." This kind of thing is really limited and unhelpful. Python has a staticmethod decorator. It also has a classmethod decorator, for which Java has no equivalent.

    This point, BTW, also included the much more helpful advice on not needlessly wrapping everything in a class. "The idiomatic translation of a Java static method is usually a module-level function".

  • The Java switch statement in Java can be implemented several ways. First, and foremost, it's usually an if elif elif elif construct. The article is unhelpful in this respect. If you're absolutely sure this is too slow (and can prove it) you can use a Python dictionary as a slightly faster mapping from value to block of code. Blindly translating switch to dictionary (without thinking) is really bad advice.

  • Don't use XML. Doesn't make sense when taken out of context. In context it means don't rely on XML to add flexibility. Java relies on describing stuff in XML; WSDL files, for example, repeat information that's obvious from inspecting the code. Python relies on introspection instead of restating everything in XML.

    But Python has excellent XML processing libraries. Several.

  • Getters and setters are not required in Python they way they're required in Java. First, you have better introspection in Python, so you don't need getters and setters to help make dynamic bean objects. (For that, you use collections.namedtuple).

    However, you have the property decorator which will bundle getters (and setters) into an attribute-like construct. The point is that Python prefers naked attributes; when necessary, we can bundle getters and setters to appear as if there's a simple attribute.

    Also, Python has descriptor classes if properties aren't sophisticated enough.

  • Code duplication is often a necessary evil in Java (e.g. method overloading), but not in Python. Correct. Python uses optional arguments instead of method overloading.

    The bullet point went on to talk about closure; that isn't as helpful as the simple advice to use default argument values wisely.

S.Lott
  • 384,516
  • 81
  • 508
  • 779
  • Although not in agreement with some of the items here, the tip about "namedtuple" was so helpful you earned an upvote. – WestCoastProjects May 29 '13 at 18:47
  • @S.Lott I want to start fresh, but I really don't want to have to go through learning things like what is a string, int, etc. Do you have any suggestions on books, or sites for someone who ants to learn Python from fresh, but already has programming experience? – Honinbo Shusaku Jul 23 '14 at 14:56
14

One thing you might be used to in Java that you won't find in Python is strict privacy. This is not so much something to look out for as it is something not to look for (I am embarrassed by how long I searched for a Python equivalent to 'private' when I started out!). Instead, Python has much more transparency and easier introspection than Java. This falls under what is sometimes described as the "we're all consenting adults here" philosophy. There are a few conventions and language mechanisms to help prevent accidental use of "unpublic" methods and so forth, but the whole mindset of information hiding is virtually absent in Python.

John Y
  • 14,123
  • 2
  • 48
  • 72
  • 6
    So basically, it seems to me that a recurring theme when comparing Java to Python is that Python trusts you much more - it gives you a lot more power, but also a much greater ability to mess things up. – froadie Feb 26 '10 at 04:56
  • Ditto on the search thing. I spent a good chunk of my first few days looking for a private equivalent. – Zach Varberg Feb 26 '10 at 06:33
  • 3
    The Python catch phrase is "We're all adults here". Python is distributed as source. What does "private" mean when you can read the source? If necessary, you just edit the source to change things. – S.Lott Feb 26 '10 at 11:54
  • I actually think this philosophy is harmful if you're not aware of the conventions. I say conventions because there's little in the way of language support, so you have to search around. I've seen a lot of python code where everything is public and, as such, it's non-obvious which methods are meant to called and which attributes are safe to change. The single underscore convention (self._blah_method()) is a better bet. It doesn't _enforce_ privacy, but it does say "you shouldn't call this unless you know what you're doing". The second option is the double underscore. – Mark Simpson Oct 05 '12 at 11:55
  • 2
    ... also I think the "we're all adults here" phrase is a double-edged sword. Yes, it makes it easier to dig in and find/modify existing code, but the downside is that it creates noise. If I download a package and I want to use it, I'm presented with many (invalid) options unless the package author followed an optional _convention_. In other languages, the parts that are irrelevant to me are encapsulated. I just see the public surface of the class. Not saying python is terrible for doing something different, just that it is a choice that comes with downsides. – Mark Simpson Oct 05 '12 at 11:59
10

The biggest one I can think of is not understanding or not fully utilizing duck typing. In Java you're required to specify very explicit and detailed type information upfront. In Python typing is both dynamic and largely implicit. The philosophy is that you should be thinking about your program at a higher level than nominal types. For example, in Python, you don't use inheritance to model substitutability. Substitutability comes by default as a result of duck typing. Inheritance is only a programmer convenience for reusing implementation.

Similarly, the Pythonic idiom is "beg forgiveness, don't ask permission". Explicit typing is considered evil. Don't check whether a parameter is a certain type upfront. Just try to do whatever you need to do with the parameter. If it doesn't conform to the proper interface, it will throw a very clear exception and you will be able to find the problem very quickly. If someone passes a parameter of a type that was nominally unexpected but has the same interface as what you expected, then you've gained flexibility for free.

dsimcha
  • 67,514
  • 53
  • 213
  • 334
  • Wow. I don't think I understand a lot of the first paragraph. I guess I'll google some of those terms and research how Python uses them :) Thanks – froadie Feb 26 '10 at 04:03
  • Ok - I'm researching, and I'm finding that it's pushing me in a similar direction as Ryan's 3rd point. This may be a very simple question to anyone with some background in Python - but what role does polymorphism play in Python? – froadie Feb 26 '10 at 04:21
  • 1
    Python has infinite polymorphism. As long as a given object has a required field or method, at runtime, at that code line, then the code will run. In other words, that object need not even have that field or method declared upfront, but can be added to the object later if you like. Polymorphism does not depend on inheritance, because duck-typing completely bypasses that compile-time requirement. – Caleb Hattingh Feb 26 '10 at 06:43
  • I guess I'm an explicit type of guy. Compile and pray just isn't my style. Python just feels like a giant step backwards in the name of laziness. – Damien Jan 16 '13 at 23:36
7

The most important thing, from a Java POV, is that it's perfectly ok to not make classes for everything. There are many situations where a procedural approach is simpler and shorter.

The next most important thing is that you will have to get over the notion that the type of an object controls what it may do; rather, the code controls what objects must be able to support at runtime (this is by virtue of duck-typing).

Oh, and use native lists and dicts (not customized descendants) as far as possible.

Caleb Hattingh
  • 9,005
  • 2
  • 31
  • 44
6

The way exceptions are treated in Python is different from how they are treated in Java. While in Java the advice is to use exceptions only for exceptional conditions this is not so with Python.

In Python things like Iterator makes use of exception mechanism to signal that there are no more items.But such a design is not considered as good practice in Java.

As Alex Martelli puts in his book Python in a Nutshell the exception mechanism with other languages (and applicable to Java) is LBYL (Look Before You Leap) : is to check in advance, before attempting an operation, for all circumstances that might make the operation invalid.

Where as with Python the approach is EAFP (it's easier to Ask for forgiveness than permission)

froadie
  • 79,995
  • 75
  • 166
  • 235
sateesh
  • 27,947
  • 7
  • 36
  • 45
1

A corrollary to "Don't use classes for everything": callbacks.

The Java way for doing callbacks relies on passing objects that implement the callback interface (for example ActionListener with its actionPerformed() method). Nothing of this sort is necessary in Python, you can directly pass methods or even locally defined functions:

def handler():
   print("click!")
button.onclick(handler)

Or even lambdas:

button.onclick(lambda: print("click!\n")) 
Rafał Dowgird
  • 43,216
  • 11
  • 77
  • 90
  • 2
    -1 - poor lambda example. lambda is intended to contain a single *expression*, not statement, and returns the value of that expression. Your lambda example, while it works, is actually returning the value returned by calling print (which is None, I believe). If you had a lambda that needed to print 2 statements, would you tell a newbie to write `lambda: print("first line") or print("second line")`? – PaulMcG Feb 26 '10 at 21:23