Python Forum
[solved] Classes, assign an attributes to a class not to instances.. - Printable Version

+- Python Forum (https://python-forum.io)
+-- Forum: Python Coding (https://python-forum.io/forum-7.html)
+--- Forum: General Coding Help (https://python-forum.io/forum-8.html)
+--- Thread: [solved] Classes, assign an attributes to a class not to instances.. (/thread-40020.html)



[solved] Classes, assign an attributes to a class not to instances.. - SpongeB0B - May-20-2023

Hi everyone,

I would like to create a class with a default dictionary attribute.
and when being Instantiated I would like to add (or not) some items to that attribute (attrib in the following example)


class CommonCar:

	attrib = {
		'wheel':4,
		'automatic':False}

	def __init__(self, addattrib=None, value=1):

		self.value = value

		if addattrib != None:
			self.attrib |= addattrib

#instantiation
polo = CommonCar({'brand':'VW'})


#Check the items inside the class CommonCar
print('CommonCar'.upper())
for k,v in CommonCar.attrib.items():
	print(k, v)

#Check the items inside [inline]attrib[/inline]
print('\npolo'.upper())
for k,v in polo.attrib.items():
	print(k, v)
Output:
COMMONCAR wheel 4 automatic False brand VW #<-------------- (should not have this item!!) POLO wheel 4 automatic False brand VW
So the output is unexpected, because the class COMMONCAR get also the merge dict. of the instantiation of polo

Any ideas ?

Thanks


RE: Classes, assign an attributes to a class not to instances.. - Gribouillis - May-20-2023

Hi @SpongeB0B , you could use a ChainMap to create a dictionary local to the instance
from collections import ChainMap

class CommonCar:

    attrib = {
        'wheel':4,
        'automatic':False}

    def __init__(self, addattrib=None, value=1):

        self.value = value

        self.attrib = ChainMap(addattrib or {}, self.attrib)

#instantiation
polo = CommonCar({'brand':'VW'})


#Check the items inside the class CommonCar
print('CommonCar'.upper())
for k,v in CommonCar.attrib.items():
    print(k, v)

#Check the items inside [inline]attrib[/inline]
print('\npolo'.upper())
for k,v in polo.attrib.items():
    print(k, v)
Output:
COMMONCAR wheel 4 automatic False POLO wheel 4 automatic False brand VW
Alternately, you could copy the default dictionary in every instance and update the copy.


RE: Classes, assign an attributes to a class not to instances.. - SpongeB0B - May-20-2023

(May-20-2023, 10:22 AM)Gribouillis Wrote: ... Alternately, you could copy the default dictionary in every instance and update the copy.
Thanks @Gribouillis, Yes that almost what I wanted to do initially but I don't get how to make it happen...


RE: Classes, assign an attributes to a class not to instances.. - Gribouillis - May-20-2023

(May-20-2023, 11:39 AM)SpongeB0B Wrote: I don't get how to make it happen...
You can do
_attrib = {
    'wheel':4,
    'automatic':False}

class CommonCar:

    def __init__(self, addattrib=None, value=1):

        self.value = value
        self.attrib = dict(_attrib)
        if addattrib:
            self.attrib.update(addatrib)
You can also have a read-only dictionary in the class instead of hiding the default dictionary.
import types

class CommonCar:

    attrib = types.MappingProxyType({
        'wheel':4,
        'automatic':False}) # read-only default attributes dictionary

    def __init__(self, addattrib=None, value=1):

        self.value = value
        self.attrib = dict(self.attrib)
        if addattrib:
            self.attrib.update(addattrib)



RE: Classes, assign an attributes to a class not to instances.. - SpongeB0B - May-20-2023

Thanks again @Gribouillis,

I've I read again the documentation about python classes and especially the mechanism between the
Class attributes and Instance attributes.

In my initial post I wanted to be able to compare a default dictionary inside a class definition against the same dict. but from a instance. In short compare the Class dict Vs the instance Dict.

So the easiest way (for me) is to create first an instance that will be the 'default' and all the rest of the instance will be the one to work with and to compare to the 'default one'.

Thumbs Up