3

I am new to python (using python 3.6).

I have some class that represents amounts of some fictional coins.

So an instance could represent say 10 bluecoins or negative sums such as -20 redcoins and so on.

I can now hold in a list several such CoinAmounts in a list. e.g.

[CoinAmount(coin='blue',amount=-10), CoinAmount(coin='blue',amount=20), 
 CoinAmount(coin='red',amount=5),   CoinAmount(coin='red',amount=-5),
 CoinAmount(coin='green',amount=5)]

I want to be able to "compress" the above list by summing each type of coin so that I will have.

[CoinAmount(coin='blue',amount=10), CoinAmount(coin='green',amount=5)]

or

[CoinAmount(coin='blue',amount=10), CoinAmount(coin='red',amount=0), CoinAmount(coin='green',amount=5)]

from which it is easy to derive the former...

My Q's are:

1) Would it make sense to have some sort of a ListOfCoinAmounts that subclasses list and adds a compress method? or should I use so CoinAmountUtils class that has a static method that works on a list and Compreses it?

2) Is there a way to ensure that the list actually holds only CoinAmounts or is this should just be assumed and followed (or both - i.e. it can be done but shouldn't ?

3) In a more general way what is the best practice "pythonic" way to handle a "List of something specific"?

voidpro
  • 1,652
  • 13
  • 27
epeleg
  • 10,347
  • 17
  • 101
  • 151
  • 3
    You don't need a "utils" class with static methods in it. They can just be functions. – khelwood Sep 07 '17 at 12:04
  • 1
    It sounds like your list of `CoinAmount`s should just be a dict like `{'red': 0, 'blue': 10, 'green': 5}`. – Aran-Fey Sep 07 '17 at 12:26
  • @Rawing... unless order is important, which is not apparent either way. Or unless the list is desirable in both uncompressed and compressed form. For me the interesting bit here is an efficient summing approach, if the lists were big and had many colors... – JL Peyret Sep 08 '17 at 05:46
  • Thanks @Rawing, though this might be a good approach in some scenarios, it is not relevant for my actual use case which is more complicated then what is described above. – epeleg Sep 10 '17 at 08:34
  • @khelwood, thanks. You are obviously right, this is a direct result of old habits from other programming languages. – epeleg Sep 10 '17 at 08:36

2 Answers2

1

Inheritance - when not used for typing - is mostly a very restricted form of composition / delegation, so inheriting from list is ihmo a bad design.

Having some CoinContainer class that delegates to a list is a much better design, in that 1/ it gives you full control of the API and 2/ it lets you change the implementation as you want (you may find out that a list is not the best container for your needs).

Also it will be easier to implement since you don't have to make sure you override all of the list methods and magicmethods, only the ones you need (cf point #1).

wrt/ type-cheking, it's usually not considered pythonic - it's the client code responsability to make sure it only passes compatible objects. If you really want some type-checking here at least use an ABC and test against this ABC, not against a fixed type.

bruno desthuilliers
  • 75,974
  • 6
  • 88
  • 118
  • Would this not mean that I will have to delegate each and every feature of a list that I would like to use here? while when inheriting I will get all of them for free (no code) and only will have to handle the ones that I actually need to modify (if at all)? – epeleg Sep 10 '17 at 08:42
  • Yes and yes - but from experience you will have to override almost all of those features anyway so at least you have full control over both the api and the implementation... – bruno desthuilliers Sep 10 '17 at 09:19
0

1) Subclassing list and having only CoinAmount type of elements in it is a good and cleaner method IMO.

2) Yes, that can be done. You can inherit the python list and override append method to check for types. A good example here : Overriding append method after inheriting from a Python List

3) A good practice is indeed extending the list and putting your customizations.

DhruvPathak
  • 42,059
  • 16
  • 116
  • 175
  • 2
    I beg to disagree on the typechecking part. This might be considered as a "good practice" in some statically typed language but not that much in Python where subclassing is almost only used for implementation, not for typing. – bruno desthuilliers Sep 07 '17 at 12:23
  • @brunodesthuilliers What would be your recommended way to ensure same type of elements i.e. `CoinAmounts` in the list ? Please share. – DhruvPathak Sep 07 '17 at 12:26
  • 2
    Just document that this code expects a `CoinAmount` or anything compatible (anything with the same API). It's suprising how well it works, and not only for throw-away scripts. Actually there are __very__ few typechecks in the existing Python codebase (Python's stdlib of course but also all major python libs, frameworks and apps). – bruno desthuilliers Sep 07 '17 at 12:38
  • @DhruvPathak which of the examples in the provided link are you referring to? – epeleg Sep 10 '17 at 08:59