Java 程序猿学 python:类属性和实例属性

内容纲要

今天学习了一下 python 的类属性和实例属性,感觉进入了一个新天地。

# 500px 用户
class User(object):
    id = 0
    name = ''

    def __init__(self, id, name):
        self.id = id
        self.name = name

这是我在做 500px 爬虫时定义的一个类。作为一个 java 程序猿,当时我脑海里是这样的

public class User {
    private int id;
    private String name;

    public User(int id, String name) {
        this.id = id;
        this.name = name;
    }

    public int getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public void setId(int id) {
        this.id = id;
    }

    public void setName(String name) {
        this.name = name;
    }
}

但是经过今天的学习以后,我发觉有哪里不对。恐怕我的理解有个很大的误区。如果我仍然想要用 python 来映射我脑海里的 java 代码,那么我应该这样写

# 500px 用户
class User(object):
    def __init__(self, id, name):
        self.id = id
        self.name = name

即,不声明类属性。实际上,java 里并不存在能对应 python 类属性的东东(即使是类的静态属性依然不完全对应),如果一定要用 java 来实现第一段 python 代码的效果,那我只能这么办

public class User {

    public static id = 0;
    public static name = "";

    private int _id;
    private String _name;

    public User(int id, String name) {
        this._id = id;
        this._name = name;
    }

    public int getId() {
        return _id;
    }

    public String getName() {
        return _name;
    }

    public void setId(int id) {
        this._id = id;
    }

    public void setName(String name) {
        this._name = name;
    }
}

这一段 java 代码没有语法错误,也能表达出第一段 python 代码的思路,但仅从 java 的角度来评价,这个代码很挫。原因就是静态变量 id, nameget/setId(), get/setName() 之间的 同名 关系令人迷惑。

也就是说,我根本不应该在 python 代码里声明类属性 id, name。我的本意是想要表示 User 类有 2 个属性,整数类型的 id 和 字符串类型的 name,但这完全是 java 的思路,到了 python 这里,就产生了副作用。

以一个 java 程序猿的语言来解释 python 的类属性,那就是 java 类的 静态变量,但 python 类的实例属性可以和类属性同名并且实例属性优先,这个在 java 里很难解释,勉强要解释的话,就是我上面那段 java 代码。

那么,如果我不在 python 类里声明类属性,就如同我在第二段 python 代码里写的那样,有什么问题呢?
问题就在于没有事先声明这个类有哪些属性,令人不安,这会导致其他人或者多年以后的自己,很难看懂这个类。或者,__init__ 里的赋值就是一种变相的属性声明?这样想来,多少有点安慰。

也许这证明我还没有真正理解 python 吧。

ps

类属性和实例属性同名并且实例属性优先,这是个大坑,为了避免掉到这个坑里,最好的做法是

  1. 不声明类属性
  2. 如果一定要声明类属性,那就重写 __init__ 方法,给类属性同名的实例属性赋初始值

我觉得最佳实践是,不声明类属性,同时重写 __init__ 方法

Java 程序猿学 python:类属性和实例属性

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注

Scroll to top
粤ICP备2020114259号 粤公网安备44030402004258