when data attributes are associated with class we call them class variables when they are associated with an instance we call them instance variables for examplevals is an instance variable because for each instance of class intsetvals is bound to different list so farwe haven' seen class variable we will use one in figure data abstraction achieves representation-independence think of the implementation of an abstract type as having several componentsimplementations of the methods of the typedata structures that together encode values of the typeand conventions about how the implementations of the methods are to use the data structures key convention is captured by the representation invariant the representation invariant defines which values of the data attributes correspond to valid representations of class instances the representation invariant for intset is that vals contains no duplicates the implementation of __init__ is responsible for establishing the invariant (which holds on the empty list)and the other methods are responsible for maintaining that invariant that is why insert appends only if it is not already in self vals the implementation of remove exploits the assumption that the representation invariant is satisfied when remove is entered it calls list remove only oncesince the representation invariant guarantees that there is at most one occurrence of in self vals the last method defined in the class__str__is another one of those special __ methods when the print command is usedthe __str__ function associated with the object to be printed is automatically invoked for examplethe code intset( insert( insert( print will print{ , (if no __str__ method were definedprint would cause something like to be printed we could also print the value of by writing print __str__(or even print intset __str__( )but using those forms is less convenient the __str__ method of class is also invoked when program converts an instance of that class to string by calling str