Class attribute metamorphosis

    A short note from the series "You have been warned."

    The transition from classical programming languages ​​to Python delivers a lot of surprises.
    We read documentation:
    For example,
    Let's play

    classVessel:#class attribute
        vtype = "boat"#instance attributedef__init__(self, name):
            self.name = name
        # ислючительно для печатиdef__str__(self):
            res= '>>'for a in inspect.getmembers( self):
                ifnot a[0].startswith("__"): res += f"{a[0]}={a[1]:<14}"for a in inspect.getmembers( self.__class__):
                ifnot a[0].startswith("__"): res += f"__class__.{a[0]}={a[1]:<14}"return res
    


    Create two objects and check the values ​​of all attributes:

    Iowa = Vessel("Iowa")
    Drum=Vessel("Drum")
    printAttr(Iowa, Drum)
    >>name=Iowa          	vtype=boat          	__class__.vtype=boat          	
    >>name=Drum          	vtype=boat          	__class__.vtype=boat 
    

    So far, all as expected.

    We will try to change vtype: this can be done in two ways, which are essentially just different syntax of the same

    Vessel.vtype = "USS boat"
    printAttr(Iowa, Drum)
    >>name=Iowa          	vtype=USS boat      	__class__.vtype=USS boat      	
    >>name=Drum          	vtype=USS boat      	__class__.vtype=USS boat      	
    Iowa.__class__.vtype = 'USS WW2 Boat'
    printAttr(Iowa, Drum)
    >>name=Iowa          	vtype=USS WW2 Boat  	__class__.vtype=USS WW2 Boat  	
    >>name=Drum          	vtype=USS WW2 Boat  	__class__.vtype=USS WW2 Boat  	
    

    And everything is fine again.

    Now we will try to do the same through the object attribute.

    Drum.vtype = 'submarine'
    printAttr(Iowa, Drum)
    >>name=Iowa          	vtype=USS WW2 Boat  	__class__.vtype=USS WW2 Boat  	
    >>name=Drum          	vtype=submarine     	__class__.vtype=USS WW2 Boat  	
    

    And here is the first surprise: despite the fact that vtype is an attribute of a class, it suddenly becomes an attribute of an object.

    Check:

    Vessel.vtype = "NAVY Museum"
    >>name=Iowa          	vtype=NAVY Museum   	__class__.vtype=NAVY Museum   	
    >>name=Drum          	vtype=submarine     	__class__.vtype=NAVY Museum   	
    

    what if…

    del Drum.vtype
    >>name=Iowa          	vtype=NAVY Museum   	__class__.vtype=NAVY Museum   	
    >>name=Drum          	vtype=NAVY Museum   	__class__.vtype=NAVY Museum   
    

    And again class attribute.

    The following expression no longer passes

    del Drum.vtype
    printAttr(Iowa, Drum)
    	del Drum.vtype
    	AttributeError: vtype
    

    And the last example that emulates class overrides and the removal of the vtype attribute.

    Drum.vtype = 'submarine'del Vessel.vtype
    printAttr(Iowa, Drum)
    >>name=Iowa          	
    >>name=Drum          	vtype=submarine     	
    

    If you start to deal with namespace-s, then this behavior becomes clear.
    However, for programmers who have previously worked with normal languages, this at least seems strange. And if we talk about large projects that are supported by several generations of developers, this may turn out to be a deadline, etc.

    Taking into account the concept of Python that everything is open to all, why not access the “cool” attributes only through __class__ or its equivalent. In my opinion, it would somehow protect against surprises and make you think 10 times before assigning something to cool attributes at the object level.

    Update: PrintAttr text

    defprintAttr(*o):for a in o:
            print(a)

    Also popular now: