Python 继承另一个类的实例
在 javascript 中通过原型链继承,可以实现子类继承父类的方法和属性。
function Bird() {
this.fly = true
}
function Pigeon(){
this.feather = 'white'
}
Pigeon.prototype = new Bird()
alert(new Pigeon().fly)
其实 Python 也可以通过代理模式实现
在 Python 的类中有个 __getattr__
专有方法在访问 attribute 不存在的时候被调用,这和 javascript 中访问实例属性不存在时就继续访问原型链很像。
class Bird(object):
def __init__(self):
self.fly = True
class Pigeon(object):
def __init__(self):
self._a = A()
self.feather = 'white'
def __getattr__(self, name):
return object.__getattribute__(self._a, name)
Pigeon().fly
Pigeon 类继承的是 Bird 类的实例属性
通过这种代理模式+装饰模式,我实现了以下需求:
- 多个子类具有相同的方法名,共同继承自父类
- 父类中实现接口,调用子类实现具体的业务功能
- 父类无需知道实现了哪些子类
情景演示:
class Someone(object):
def __init__(self):
self.speak = 'haha'
def __getattr__(self, name):
if not name[0].isupper():
return object.__getattribute__(self, name)
def __getattr(cls, name):
return object.__getattribute__(self, name)
try:
cls = eval(name)
except:
print('No %s' % name)
raise NotImplementedError
cls.__getattr__ = __getattr
instance = cls()
setattr(self, name, instance)
return instance
class Tom(object):
def run(self):
return 'running Tom'
class Jerry(object):
def run(self):
return 'running Jerry'
men = Someone()
print(men.speak)
print(men.Tom.run())
print(men.Jerry.run())
# haha
# running Tom
# running Jerry
子类 TOM 和 Jerry 并没有显式继承 Speaker,而且实例化的是父类 Speaker,调用子类名称空间的时候自动实例化
实际应用时,上面的类可能不在同一个文件中,这时候可以通过动态加载类或包来实现
# -*- coding: utf-8 -*-
import importlib
# someone.py
class Action(object):
_pkg_base = 'some/path/'
def __getattr__(self, name):
pkg = _pkg_base + name
try:
module = importlib.import_module(pkg)
Action = module.Action
except ImportError:
Action = object
def __getattr(cls, name):
return object.__getattribute__(cls._myself, name)
Action.__getattr__ = __getattr
instance = Action()
instance._myself = self
setattr(self, name, instance)
return instance
# tom.py
class Action(object):
def run(self):
return 'running Tom'
# jerry.py
class Action(object):
def run(self):
return 'running Jerry'