Inheritance#2
Conversation
How parts depend on one anotherThe core of this is the The statistical and scalar combiners are then instances of these, supplied with specific methods that mean they can be used to calculate the named statistic. graph TD
Combiner -- implements --> CombinerProtocol
SumCombiner -- implements --> CombinerProtocol
Combiner -- uses --> build_combine_function
SumCombiner -- uses --> build_combine_function
statistical_combiners -- instances of --> SumCombiner
scalar_combiners -- instances of --> Combiner
What's with the protocols?The combiner instances have combine methods that have input types that are protocols. This means the methods work to any object that exposes the right properties. Want to use a This extends to the Dependency overviewgraph TD
subgraph partials
protocol(Partial protocols)
mean(Mean partial)
variance(Variance partial)
end
subgraph combiners
core
scalar
statistical
end
stat_aggregators
scalar -- implements --> core
statistical -- implements --> core
mean -- implements --> protocol
variance -- implements --> protocol
statistical -- uses --> protocol
stat_aggregators -- uses --> protocol
stat_aggregators -- uses --> statistical
Existing APIThe API I wish to define should provide some out-of-the-box classes for common statistics that can either be used in another class or be used in notebooks. It should be easy to extend, either using the existing combiners to calculate federated statistics on user-defined objects, or to provide (with the
|
PR Description
We talked about the value of atomic classes for each statistic aggregation versus having one class with
Nonedefaults for the possible values and errors thrown on trying to call the methods to calculate incompatible statistics.The fact that we had such divergent opinions led me to believe that we were both wrong.
This is my attempt to do it right.
Protocols
We want the data held by a class to be compatible with multiple final results.
For example, anything that holds the data to compute a sample's variance can also calculate the count, sum, and mean.
Python will just do this anyway through duck-typing, but your LSP will shout at you with the existing version.
I've used protocols here for structural typing.
As the data for variance holds the data for count, sum, and mean, the
VariancePartialProtocolinherits from the preceding protocols.LSP then happy
Composite Aggregators
So much for the protocols, but we need concrete objects that can do the work.
The
stat_aggregatorsmodule exposesStatAggregators, which hold data, and have properties for calculating the relevant statistics.I think this provides a convenient API for the underlying logic.
There's a small amount of repetition, but the use of protocols for the types in combiners keeps this pretty short