开发者

Inheritance of from_<type> in Python

开发者 https://www.devze.com 2023-04-01 04:09 出处:网络
Edit: There was some confusion, but I want to ask a general question about object oriented design in Python.

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 ide开发者_高级运维ntical 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!


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
0

精彩评论

暂无评论...
验证码 换一张
取 消