1

I am working on code in Python that creates Compound objects (as in chemical compounds) that are be composed of Bond and Element objects. These Element objects are created with some inputs about them (Name, symbol, atomic number, atomic mass, etc). If I want to populate an array with Element objects, and I want the Element objects to be unique so I can do something to one and leave the rest unchanged, but they should all have the information related to a 'Hydrogen' element.

This question Python creating multiple instances for a single object/class leads me to believe that I should create sub-classes to Element - ie a Hydrogen object and a Carbon object, etc.

Is this doable without creating sub-classes, and if so how?

Community
  • 1
  • 1
Dan Oberlam
  • 2,435
  • 9
  • 36
  • 54
  • What do you mean by "sub-object"? – user2357112 Jan 24 '14 at 21:09
  • 2
    Like the asker in the question you linked to, I think you too are confused about classes and objects. If ```Element``` is a class, and you create an instantiate that class to represent hydrogen, you have made a "hydrogen object". You can use the same class to create a "carbon object" or "iron object" and so on. All of these objects are independent (except in some [special cases](http://stackoverflow.com/questions/1132941/least-astonishment-in-python-the-mutable-default-argument)) – wnnmaw Jan 24 '14 at 21:12
  • instance1 = Class(args). Instance2 = Class(args). Two identical but unique instances. Also look into copy module. – Max Jan 24 '14 at 21:12
  • You might want to read up on the differences between [prototype-based](http://en.wikipedia.org/wiki/Prototype-based_programming) and [class-based](http://en.wikipedia.org/wiki/Class-based_programming) object-oriented programming. Python, and most other languages, are class-based, but there are some (notably JavaScript) that work the way you seem to be expecting. – abarnert Jan 24 '14 at 21:22
  • @wnnmaw and Max - that's what I thought too, until printing the array showed that 'distinct' objects all had the same pointer. Unless I'm misunderstanding how pointers work that indicates to me that they're all identical objects – Dan Oberlam Jan 24 '14 at 21:54
  • @user2357112 I meant subclass, my mistake – Dan Oberlam Jan 24 '14 at 21:55
  • Does your Element class cache instances? They won't normally be the same object. – Max Jan 24 '14 at 22:45

1 Answers1

6

Design your object model based on making the concepts make sense, not based on what seems easiest to implement.

If, in your application, hydrogen atoms are a different type of thing than oxygen atoms, then you want to have a Hydrogen class and an Oxygen class, both probably subclasses of an Element class.*

If, on the other hand, there's nothing special about hydrogen or oxygen (e.g., if you don't want to distinguish between, say, oxygen and sulfur, since they both have the same valence), then you don't want subclasses.

Either way, you can create multiple instances. It's just a matter of whether you do it like this:

atoms = [Hydrogen(), Hydrogen(), Oxygen(), Oxygen()]

… or this:

atoms = [Element(1), Element(1), Element(-2), Element(-2)]

If your instances take a lot of arguments, and you want a lot of instances with the same arguments, repeating yourself like this can be a bad thing. But you can use a loop—either an explicit statement, or comprehension—to make it better:

for _ in range(50):
    atoms.append(Element(group=16, valence=2, number=16, weight=32.066))

… or:

atoms.extend(Element(group=16, valence=2, number=16, weight=32.066) 
             for _ in range(50))

* Of course you may even want further subclasses, e.g., to distinguish Oxygen-16, Oxygen-17, Oxygen-18, or maybe even different mixtures, like the 99.762% Oxygen-16 with small amounts of -18 and tiny bits of the others that's standard in Earth's atmosphere, vs. the different mixture that was common millions of years ago…

abarnert
  • 354,177
  • 51
  • 601
  • 671
  • While the concept of classes as "types of things" certainly suggests making `Hydrogen` and `Oxygen` subclasses, I don't think this approach scales to 118 different elements. I'd go with a different way of distinguishing elements. – user2357112 Jan 24 '14 at 21:20
  • @user2357112: It really depends on your app. For one thing, you may not _have_ 118 different types of things. For another, the subclasses can themselves be dynamic if it's necessary—e.g., create them and store them in a dict under their name or atomic number, and then instead of `Hydrogen()*2 + Oxygen()` you can have `elements['hydrogen']()*2 + elements['oxygen']()*2`. – abarnert Jan 24 '14 at 21:24
  • Since elements have a lot of data constants associated with them, I'd go with the subclassing method and class attributes to describe them. – Keith Jan 24 '14 at 21:37