What failed when going from Javaer to Pythonista

at first

This is the article in charge of 12/2 of PyCon JP Advent Calendar 2016. There are other interesting articles, so if you are interested, please do. There are places where Java is written, but since it's been a while, it may be wrong, so I hope you can read it while observing the atmosphere.

Purpose

As the subject says, I'll share the mistakes I've made so that those who read this can make the transition from Javaer to Pythonista smooth.

Self-introduction

A member of PyCon JP 2017. Speaking of activities related to PyCon, Talk in 2015 and LT in 2016 / watch? v = O1-9Yv9cB8Q & t = 820s). I was also a lecturer at the 1st Python Boot Camp. Twitter account is @horobi_gengar

History so far

Regarding the subject matter, I think it is necessary, so I will briefly explain the language used in development so far.

Order Enrollment period Main language Supplement
1st company Two-and-a-half years nothing special c or vb. Flexible according to the site
2nd company 5 and a half years Java Besides, JavaScript, Delphi, COBOL, etc.
3rd company 5 months nothing special C#And PHP little by little
4th company 2 years Python Very rarely involved in Ruby
5th company 3 months(Ongoing) Python Write JavaScript once in a while

So, this story is about the 4th company.

What failed

I wrote one file in one class

I made a lot of mistakes, but this was the biggest one. Java is basically described in one file and one class (with exceptions), but Python often describes multiple classes in one file. In terms of image, Python must be written with an image that has one less package hierarchy than Java.

I will explain it together with the image of the package (folder structure). For example, if it is DAO to access the users table in the common module

common  └db   └dao

Create a file called Users.java under the package called Users, and create a class called Users in it.

And if you want to use that Users class from another class,

Users.java


package common.db.dao.Users

users = new Users()
user = users.getUser(1)

It feels like. However, if you write in Python with the same package structure,

users.py


from common.db.dao.users import Users 

users = Users()
user = users.get_user(1)

It becomes like this, and the end of from and the contents of import are overlaid, which is helpful. So, in this case, create dao.py under the db package, describe the Users class in it, and

users.py


from common.db.dao import Users 

users = Users()
user = users.get_user(1)

It should be described like this. (This seems to be a big deal for the size of the dao file, but it's just an example) This failure led to a gentle fix for a module that had some track record of operation.

I made all internal variables public.

In Java, you can explicitly specify whether it can be referenced from the outside by prefixing the internal variable of the class with public or private.

User.java



public class User{
    public int userId;          //Accessable from outside the class
    private String userName; //Inaccessible from outside the class
    public User(int userId, String userName){
        this.userId = userId
        this.userName = userName
  }
}

User u = new User(1, "Yamada Taro")
System.out.println(u.userId)  //safe
System.out.println(u.userName)//out

On the other hand, in the case of Python, by adding "_ (underscore)" to the variable name, it is possible to control public and private in Java. (If you want to do it, you can refer to it.)

user.py


class User(object):
    def __init__(self, user_id, user_name):
        self.user_id = user_id       #Accessable from outside the class
        self.__user_name = user_name #Inaccessible from outside the class

u = User(1, 'Yamada Taro')
print(u.uer_id)     #safe
print(u.__user_name)#out

Well, when I started writing Python, I misunderstood what I thought about, and I remembered the following language specifications.

user.py


class User(object):
    user_id = 0                    #If you write it in this place, you can access it from outside the class
    def __init__(self, user_id, user_name):
        self.user_id = user_id       
        self.user_name = user_name #If not written, it will be treated as private

u = User(1, 'Yamada Taro')
print(u.uer_id)   #safe
print(u.user_name)#out(I thought)

Why did this happen? Of course, user_name can be accessed from the outside as much as you want. When I noticed this, chills ran on my back, and a festival with two underscores was to be held.

I have made a getter / setter.

In the case of Java, do not specify internal variables as public, but create getters and setters considering the range of influence etc.

User.java



public class User{
    private int userId;         //Keep internal variables inaccessible from the outside
    private String userName;
    public User(int userId, String userName){
        this.userId = userId
        this.userName = userName
    }
    public int getUserId(){
        return this.userId;
    }
    public int getUserName(){
        return this.userName;
    }
}

User u = new User(1, "Yamada Taro")
System.out.println(u.getUserId())  //Encapsulate by sandwiching a function instead of calling an internal variable directly
System.out.println(u.getUserName())

After all, Eclipse has a function to create getters and setters all at once. So I did the same thing in Python.

user.py



class User(object):
    def __init__(self, user_id, user_name):
        self.__user_id = user_id
        self.__user_name = user_name

    def get_user_id(self):
        return self.__user_id

    def get_user_name(self):
        return self.__user_name


u = User(1, 'Yamada Taro')
print(u.get_user_id())
print(u.get_user_name())#Use it like this

One of the merits of a so-called lightweight language like Python is "small amount of code". This bad description method is the very baddest know-how that completely erases its merits. Sorry. In the case of Python, this is fine.

user.py



class User(object):
    def __init__(self, user_id, user_name):
        self.user_id = user_id       #No more underscores if they can be accessed directly from the outside
        self.user_name = user_name

u = User(1, 'Yamada Taro')
print(u.user_id)
u.user_name = 'Jiro Suzuki' #You can access it as much as you want, but this is fine! !! !!

If you really care about it, you should use property as well.

user.py



class User(object):
    def __init__(self, user_id, user_name):
        self.__user_id = user_id
        self.__user_name = user_name

    @property                          #If it is read-only, it looks like this
    def user_id(self):
        return self.__user_id

    @property
    def user_name(self):
        return self.__user_name


u = User(1, 'Yamada Taro')
print(u.user_id)       #safe
u.user_name = 'Jiro Suzuki' #out! !! !! !!

It's important to write properly.

Afterword

Several times so far "Python you wrote is Java-like" "I'm a Javaer, but the Python you wrote is easy to read." I was told that I was very concerned about it, so I wrote this article. After all, compared to Python written by someone who has written other lightweight languages for a long time, Python I wrote is somewhat stiff and Java-like. I've been writing Python for two years now, so I think the Java odor has disappeared, but I'll continue to devote myself every day.

Recommended Posts

What failed when going from Javaer to Pythonista
What I did when updating from Python 2.6 to 2.7
What to do when Ubuntu crashes
What I referred to when studying tkinter
Points to note when switching from NAOqi OS 2.4.3 to 2.5.5
What to do when PermissionError of tempfile.mkstemp occurs
What to do if you get a memory error when converting from PySparkDataFrame to PandasDataFrame
Sum from 1 to 10
curl: (60) What to do when Issuer certificate is invalid.
What to do when gdal_merge creates a huge file
What to do when raise ValueError, "unsupported hash type"
Python --Notes when converting from str type to int type
Speeding up when connecting from cx_Oracle to Autonomous Database
What to do when "cannot import name xxx" [Python]
What I was addicted to when using Python tornado
What to do when you can't bind CaboCha to Python
What to do when you get an error saying "Name resolution temporarily failed" on linux