8wDlpd.png
8wDFp9.png
8wDEOx.png
8wDMfH.png
8wDKte.png

在 Python 中将对象转换为子类?

Homr Zodyssey 1月前

43 0

假设我有一个无法更改的库函数,它会生成一个 A 类的对象,而且我创建了一个从 A 继承的 B 类。使用该库函数最直接的方法是什么?

假设我有一个无法更改的库函数,它会生成一个 A 类的对象,并且我创建了一个从 A 继承的 B 类。

使用库函数生成 B 类对象的最直接方法是什么?

编辑-我在评论中被要求提供更多详细信息,因此如下:

PyTables 是一个处理 Python 分层数据集的包。我最常用的是它能够管理部分位于磁盘上的数据。它提供了一种仅带有扩展切片的“Array”类型,但我需要选择任意行。Numpy 提供了此功能 - 您可以通过提供与要选择的数组长度相同的布尔数组来进行选择。因此,我想对 Array 进行子类化以添加此新功能。

从更抽象的意义上讲,这是我以前考虑过的一个问题。通常的解决方案就像已经建议的那样 - 为 B 创建一个构造函数,该构造函数接受 A 和其他参数,然后提取 A 的相关位以插入到 B 中。由于这似乎是一个相当基本的问题,我提出这个问题,看看是否有我不知道的标准解决方案。

帖子版权声明 1、本帖标题:在 Python 中将对象转换为子类?
    本站网址:http://xjnalaquan.com/
2、本网站的资源部分来源于网络,如有侵权,请联系站长进行删除处理。
3、会员发帖仅代表会员个人观点,并不代表本站赞同其观点和对其真实性负责。
4、本站一律禁止以任何方式发布或转载任何违法的相关信息,访客发现请向站长举报
5、站长邮箱:yeweds@126.com 除非注明,本帖由Homr Zodyssey在本站《oop》版块原创发布, 转载请注明出处!
最新回复 (0)
  • 由于库函数返回 A,因此如果不进行更改,就无法使其返回 B。

    您可以做的一件事是编写一个函数来获取 A 实例的字段并将其复制到新的 B 实例中:

    class A: # defined by the library
        def __init__(self, field):
            self.field = field
    
    class B(A): # your fancy new class
        def __init__(self, field, field2):
            self.field = field
            self.field2 = field2 # B has some fancy extra stuff
    
    def b_from_a(a_instance, field2):
        """Given an instance of A, return a new instance of B."""
        return B(a_instance.field, field2)
    
    
    a = A("spam") # this could be your A instance from the library
    b = b_from_a(a, "ham") # make a new B which has the data from a
    
    print b.field, b.field2 # prints "spam ham"
    

    编辑:根据您的情况, 组合而不是继承 可能是一个不错的选择;也就是说,您的 B 类可以只包含 A 的实例,而不是继承:

    class B2: # doesn't have to inherit from A
        def __init__(self, a, field2):
            self._a = a # using composition instead
            self.field2 = field2
    
        @property
        def field(self): # pass accesses to a
            return self._a.field
        # could provide setter, deleter, etc
    
    a = A("spam")
    b = B2(a, "ham")
    
    print b.field, b.field2 # prints "spam ham"
    
  • Python 对象通过设置 .__class__ 属性来了解其类。您实际上可以将其设置为其他值:.com/a/29256784/1423333

  • 我赞成使用 @property 从 self._a 中提取数据。组合有助于编写纯方法,这更容易进行单元测试。继承并没有错,它实际上取决于您的用例。但我的经验表明,从长远来看,组合往往更容易处理。

  • 在我看来,除非你绝对确定已经将对象 A 的全部内容复制到对象 B 中,否则你无法保证你的对象 B 的行为将与创建它的对象 A 的行为相同。此时你实际上不再进行继承了。

  • 如果构造函数执行副作用,则第二种方法是强制性的。序列化为 json 时,第一种方法效果更好。

  • 如果子类的初始化程序可以处理它,或者您编写了显式升级程序,则可以做到这一点。以下是一个例子:

    class A(object):
        def __init__(self):
            self.x = 1
    
    class B(A):
        def __init__(self):
            super(B, self).__init__()
            self._init_B()
        def _init_B(self):
            self.x += 1
    
    a = A()
    b = a
    b.__class__ = B
    b._init_B()
    
    assert b.x == 2
    
  • 我必须说这是最伟大的黑客解决方案。 +1 | Google 员工还必须检查:.com/questions/49718703/…

  • 问题的部分难点在于我不一定有权访问类 A 的构造函数,而可能只是访问返回 A 的类方法。在这种情况下,我认为这个解决方案不起作用。

  • 引用 10

    如果你知道自己在做什么, .__class__ 你实际上可以改变 对象的属性

    In [1]: class A(object):
       ...:     def foo(self):
       ...:         return "foo"
       ...:
    
    In [2]: class B(object):
       ...:     def foo(self):
       ...:         return "bar"
       ...:
    
    In [3]: a = A()
    
    In [4]: a.foo()
    Out[4]: 'foo'
    
    In [5]: a.__class__
    Out[5]: __main__.A
    
    In [6]: a.__class__ = B
    
    In [7]: a.foo()
    Out[7]: 'bar'
    
  • 类 B 是否应该从 A 继承以更好地匹配原始问题?此外,如果您要重写方法,调用 super().foo() 可能是明智之举(当然,除非您打算删除原始功能 :-) )

  • 引用 12

    用 Monkeypatch 修补图书馆?

    例如,

    import other_library
    other_library.function_or_class_to_replace = new_function
    

    噗,它会返回您想要它返回的任何东西。

    Monkeypatch A. new 返回 B 的一个实例?

    调用 obj = A() 后,将结果更改为 obj.= class B?

  • 根据用例,你现在可以破解数据类,以使组合解决方案更加清晰:

    from dataclasses import dataclass, fields
    
    @dataclass
    class B:
        field: int  # Only adds 1 line per field instead of a whole @property method
    
        @classmethod
        def from_A(cls, a):
            return cls(**{
                f.name: getattr(a, f.name)
                for f in fields(A)
            })
    
返回
作者最近主题: