from_的继承在Python中

发布于 2024-12-02 22:54:50 字数 975 浏览 0 评论 0原文

编辑:有一些困惑,但我想问一个关于Python中面向对象设计的一般问题。

考虑一个可以让您将数据值映射到计数或频率的类:

class DataMap(dict):
    pass

现在考虑一个子类,它允许您从数据列表构建直方图:

class Histogram(DataMap):
    def __init__(self, list_of_values):
        # 1. Put appropriate super(...) call here if necessary
        # 2. Build the map of values to counts in self
        pass

现在考虑一个类,它可以让您制作平滑的概率质量表而不是直方图。

class ProbabilityMass(DataMap):
    pass

允许从直方图或值列表构造ProbabilityMass最佳方法是什么?

我是在 C++ 中“长大”的,在这种情况下,我会使用重载的构造函数。在Python中,我考虑过这样做:

  • 构造函数采用多个参数(除了其中一个之外的所有参数都应该==无)
  • 我定义了 from_Histogram 和 from_list 方法

在第二种情况下(我认为更好),最好的方法是什么允许 from_list 方法使用 Histogram 构造函数中的共享代码? ProbabilityMass 表与 Histogram 表几乎相同,但它经过缩放,以便所有值的总和为 1.0。

如果您遇到过类似问题,请分享您的专业知识!

Edit: There was some confusion, but I want to ask a general question about object oriented design in Python.

Consider a class that lets you map data values to counts or frequencies:

class DataMap(dict):
    pass

Now consider a subclass that allows you to construct a histogram from a list of data:

class Histogram(DataMap):
    def __init__(self, list_of_values):
        # 1. Put appropriate super(...) call here if necessary
        # 2. Build the map of values to counts in self
        pass

Now consider a class that lets you make a smoothed probability mass table rather than a Histogram.

class ProbabilityMass(DataMap):
    pass

What is the best way to allow a ProbabilityMass to be constructed from either a Histogram or a list of values?

I "grew up" programming in C++, and in this case I would use an overloaded constructor. In Python I've thought of doing this with:

  • The constructor takes multiple arguments (all but one of these should == None)
  • I define from_Histogram and from_list methods

In the second case (which I believe is better), what is the best way to allow the from_list method to use the shared code from the Histogram constructor? A ProbabilityMass table is nearly identical to a Histogram table, but it is scaled so that the sum of all value is 1.0.

If you have come across a similar problem, please share your expertise!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

偏闹i 2024-12-09 22:54:50

首先,如果您认为需要 @staticmethod,那么您几乎总是不需要。该函数要么不是类的一部分,在这种情况下它应该只是一个自由函数,要么它是类的一部分,但不绑定到实例,并且它应该是一个 @classmethod 。您的命名构造函数是 @classmethod 的良好候选者。

另请注意,您应该通过 super()B 调用 A.__init__,否则多重继承会给您带来不好的影响。

class A:
    def __init__(self, data):
        self.values_to_counts = {}
        for val in data:
            if val in self.values_to_counts:
                self.values_to_counts[val] += 1
            else:
                self.values_to_counts[val] = 1
    @classmethod
    def from_values_to_counts(cls, values_to_counts):
        self = cls([])
        self.values_to_counts = values_to_counts
        return self

class B(A):
    def __init__(self, data, parameter):
        super(B, self).__init__(data)
        self.parameter = parameter
    def print_parameter(self):
        print self.parameter

在这种情况下,您不需要 B.from_values_to_counts,它继承自 A,并且它将返回 B 的实例,因为这就是它的名字。

如果您需要在 B 中进行更复杂的初始化,可以使用 super(),它看起来与在实例中使用它时的方式非常相似。毕竟,classmethod 实际上并不比 instancemethod 更复杂,其中 im_self 属性被分配给类本身。

class A:
    def __init__(self, data):
        self.values_to_counts = {}
        for val in data:
            if val in self.values_to_counts:
                self.values_to_counts[val] += 1
            else:
                self.values_to_counts[val] = 1
    @classmethod
    def from_values_to_counts(cls, values_to_counts):
        self = cls([])
        self.values_to_counts = values_to_counts
        return self

class B(A):
    def __init__(self, data, parameter):
        super(B, self).__init__(data)
        self.parameter = parameter
    def print_parameter(self):
        print self.parameter
    @classmethod
    def from_values_to_counts(cls, values_to_counts):
        self = super(B, cls).from_values_to_counts(values_to_counts)
        do_more_initialization(self)
        return self

To start with, if you think you want @staticmethod, you almost always don't. Either the function is not part of the class, in which case it should just be a free function, or it is part of the class, but not tied to an instance, and it should be a @classmethod. Your named constructor is a good candidate for a @classmethod.

Also note that you should invoke A.__init__ from B via super(), otherwise multiple inheritance can bite you bad.

class A:
    def __init__(self, data):
        self.values_to_counts = {}
        for val in data:
            if val in self.values_to_counts:
                self.values_to_counts[val] += 1
            else:
                self.values_to_counts[val] = 1
    @classmethod
    def from_values_to_counts(cls, values_to_counts):
        self = cls([])
        self.values_to_counts = values_to_counts
        return self

class B(A):
    def __init__(self, data, parameter):
        super(B, self).__init__(data)
        self.parameter = parameter
    def print_parameter(self):
        print self.parameter

In this case, you don't need a B.from_values_to_counts, it inherits from A, and it will return an instance of B, since that's how it was called.

If you need to do more complex initialization in B, you can, using super(), which looks very similar to the way it would when you use it with instances. after all, a classmethod really isn't anything more complex than an instancemethod where the im_self attribute is assigned to the class itself.

class A:
    def __init__(self, data):
        self.values_to_counts = {}
        for val in data:
            if val in self.values_to_counts:
                self.values_to_counts[val] += 1
            else:
                self.values_to_counts[val] = 1
    @classmethod
    def from_values_to_counts(cls, values_to_counts):
        self = cls([])
        self.values_to_counts = values_to_counts
        return self

class B(A):
    def __init__(self, data, parameter):
        super(B, self).__init__(data)
        self.parameter = parameter
    def print_parameter(self):
        print self.parameter
    @classmethod
    def from_values_to_counts(cls, values_to_counts):
        self = super(B, cls).from_values_to_counts(values_to_counts)
        do_more_initialization(self)
        return self
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文