Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

are user defined classes mutable

Say I want to create a class for car, tractor and boat. All these classes have an instance of engine and I want to keep track of all the engines in a single list. If I understand correctly if the motor object is mutable i can store it as an attribute of car and also the same instance in a list.

I cant track down any solid info on whether user defined classes are mutable and if there is a choice to choose when you define them, can anybody shed some light?

like image 726
jonathan topf Avatar asked Aug 22 '12 15:08

jonathan topf


People also ask

Which data type is not mutable in Python?

Objects of built-in type that are immutable are: Numbers (Integer, Rational, Float, Decimal, Complex & Booleans) Strings. Tuples.

Are Python classes immutable?

Mutable and Immutable Data Types in Python. Some of the mutable data types in Python are list, dictionary, set and user-defined classes. On the other hand, some of the immutable data types are int, float, decimal, bool, string, tuple, and range.

Which data types are mutable in Python?

List, Sets, and Dictionary in Python are examples of some mutable data types in Python. Immutable data types are those, whose values cannot be modified once they are created. Examples of immutable data types are int, str, bool, float, tuple, etc.


1 Answers

User classes are considered mutable. Python doesn't have (absolutely) private attributes, so you can always change a class by reaching into the internals.

For using your class as a key in a dict or storing them in a set, you can define a .__hash__() method and a .__eq__() method, making a promise that your class is immutable. You generally design your class API to not mutate the internal state after creation in such cases.

For example, if your engines are uniquely defined by their id, you can use that as the basis of your hash:

class Engine(object):     def __init__(self, id):         self.id = id      def __hash__(self):         return hash(self.id)      def __eq__(self, other):         if isinstance(other, self.__class__):             return self.id == other.id         return NotImplemented 

Now you can use instances of class Engine in sets:

>>> eng1 = Engine(1) >>> eng2 = Engine(2) >>> eng1 == eng2 False >>> eng1 == eng1 True >>> eng1 == Engine(1) True >>> engines = set([eng1, eng2]) >>> engines set([<__main__.Engine object at 0x105ebef10>, <__main__.Engine object at 0x105ebef90>]) >>> engines.add(Engine(1)) >>> engines set([<__main__.Engine object at 0x105ebef10>, <__main__.Engine object at 0x105ebef90>]) 

In the above sample I add another Engine(1) instance to the set, but it is recognized as already present and the set didn't change.

Note that as far as lists are concerned, the .__eq__() implementation is the important one; lists don't care if an object is mutable or not, but with the .__eq__() method in place you can test if a given engine is already in a list:

>>> Engine(1) in [eng1, eng2] True 
like image 66
Martijn Pieters Avatar answered Oct 12 '22 19:10

Martijn Pieters