Python 中的属性覆盖和猴子补丁

一般说,在基类中定义的访问基类中属性的方法,即使派生类覆盖他也不会造成影响,没懂?

我的意思是这个 举一个简单的例子

public class Person {
    private final String _name = "person";

    public String getName() {
        return this._name;
    }
}

public class Worker extends Person {
    private final String _name = "worker";
}

你应该不会疑惑当我实例化 Worker 类然后再在调用 getName 方法应该返回的是 person 吧。

但是在 py 中就不不是这样,例如:

class Person:
  def __init__(self):
    self._name = 'person'
  
  def get_name(self):
    return self._name

class Worker(Person):
  def __init__(self):
    self._name = 'worker'

# >>> w = Worker()
# >>> w.get_name()
# 'worker'

不仅是对象属性会表现出这样的特点,对于类属性(或者如果按java的叫法应该叫做静态属性)也会如此。

所以假如你在代码中做了这样的事情的话,可能会出现奇怪的问题,假使你重来没有遇到过这种问题,也算正常,毕竟在父子类中起一个重复的变量名好像没有什么特别的好处,也算不上好实践

PS;好像需要收回这句话,Django源码中经常这样做,并且在利用行为

那么接下来在来看一下猴子补丁还是以上面定义的 py 代码为例:

def get_name(self):
  return 'new name'

Worker.get_name = get_name # 用 Person.get_name = get_name 也是一样滴~~
w.get_name
# >>> 'new name'

运行时改变行为,这个就叫猴子补丁

当然还有就是这边直接修改的时未绑定方法,如果修改绑定方法的话,那么就不需要 self 参数了,如

def get_name():
  return 'foo'

w.get_name = get_name
w.get_name()
# >>> 'foo'

啥叫绑定(bind),啥叫未绑定呢?

可以注意到在类中定义的成员方法时候都需要传递一个 self 参数,然而在对象实例话以后成员函数的 self 参数却又不需要传递了,也就是说该对象的成员函数中的 self 参数和该对象绑定了

PS: 了解一点JS的可能觉得也不算太奇怪,因为 JS 就有 call、apply 和 bind 函数,略略略

而在类中,他们还是尚未绑定的,例如我们可以这样调用尚未绑定的方法

Person.get_name(w)
# >>> 'worker'
原文地址:https://www.cnblogs.com/freesfu/p/15695109.html