【问题标题】:How to make a python instance inherit all of the behavior of one of its attributes?如何使 python 实例继承其属性之一的所有行为?
【发布时间】:2018-02-27 00:13:07
【问题描述】:

假设我有一个 python 类:

class A:
    baz = 1

    def bar(self, x):
        return self.baz * x

现在假设我有第二个类,将第一个类的一个实例作为属性:

class B:
    def __init__(self, a, z):
        self.a = a
        self.z = z

    @property
    def baz(self):
        return z

注意B 不是从类A 继承的;它甚至没有意识到这一点。

我怎样才能使B 的实例 A 的实例,除了B 的定义中明确给出的行为?例如,如果我想要

a = A()
b = B(a, 2)
assert b.bar(2) == 4

也就是说,使用A.bar,但将b 传递为self。要获得这种行为,仅仅做类似的事情是不够的

class B:
    ...

    def getattr(self, attribute):
        return getattr(self.a, attribute)

这将允许在self.a 上查找未在self 上定义的任何方法。这适用于常量和静态方法,但对于实例方法它是错误的,因为b.bar 将解析为A.bar,而self 绑定到b.a

基本上,我想要做的是将A(或更一般地说,无论B.__init__ 中的a 的类型是什么)动态插入到该实例的MRO 中。换句话说,让B 继承自a 的任何类型,基于每个实例。

这样的事情可能吗?

【问题讨论】:

    标签: python oop metaprogramming


    【解决方案1】:

    一个hacky方法:你可以在__getattr__中自己绑定方法,注意,所有函数都是描述符,所以他们有一个__get__方法!

    In [47]: class A:
        ...:     baz = 1
        ...:
        ...:     def bar(self, x):
        ...:         return self.baz * x
        ...:
        ...:
        ...: class B:
        ...:     def __init__(self, a, z):
        ...:         self.a = a
        ...:         self.z = z
        ...:
        ...:     @property
        ...:     def baz(self):
        ...:         return self.z
        ...:
        ...:     def __getattr__(self, attribute):
        ...:         try:
        ...:             attr =  getattr(type(self.a), attribute)
        ...:         except AttributeError:
        ...:             return getattr(self.a, attribute)
        ...:
        ...:         if callable(attr):
        ...:             return attr.__get__(self)
        ...:         return attr
        ...:
        ...:
        ...:
    
    In [48]: a = A()
        ...: b = B(a, 2)
        ...: b.bar(2)
        ...:
    Out[48]: 4
    

    【讨论】:

      猜你喜欢
      • 2020-05-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-04-24
      • 1970-01-01
      • 2022-01-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多