Attribut och metoder i Python

Attribut och metoder är centrala komponenter i objektorienterad programmering (OOP) som hjälper till att definiera klassernas data (attribut) och beteende (metoder).

Vad är attribut?

Attribut är variabler som är bundna till de klasser eller objekt de definieras i och i Python finns det två huvudtyper av attribut: instansattribut och klassattribut.

  • Instansattribut:
    Dessa attribut är specifika för varje instans av en klass. D.v.s. att alla objekt av klassen Car har attributet make, men värdet på attributet kommer vara unikt för varje instans. Vi har tidigare sett exempel på detta när vi har arbetat med konstruktorn (__init__):
      class Car:
          def __init__(self, make, model):
              self.make = make        ## Instance attribute
              self.model = model      ## Instance attribute
    
  • Klassattribut:
    Dessa attribut är istället gemensamma för alla instanser av en klass. D.v.s. att alla objekt av klassen Car skulle kunna ha attributet number_of_wheels med värdet 4 då detta är något som delas av hela klassen. Exempelvis enligt:
      class Car:
          number_of_wheels = 4        ## Class attribute
    
          def __init__(self, make, model):
              self.make = make        ## Instance attribute
              self.model = model      ## Instance attribute
    

För att peka på och arbeta med instansattribut har vi i föregående kapitel diskuterat punktnotationen på instansnivå. För att istället peka på och arbeta med klassattribut så nyttjas fortfarande punktnotation, men på klassnivå.

class Car:
    number_of_wheels = 4        

    def __init__(self, make, model):
        self.make = make        
        self.model = model    

print(Car.number_of_wheels)  
4

Noterbart är dock att det fortfarande är möjligt att komma åt klassattribut genom en instans. Exempelvis enligt:

class Car:
    number_of_wheels = 4        

    def __init__(self, make, model):
        self.make = make        
        self.model = model    

print(Car.number_of_wheels)
car_a = Car("Volvo", "XC90")
print(car_a.number_of_wheels) 
4
4

Det är dessutom, i Python, möjligt att manipulera klassvariabler som om de vore instansvariabler då objekt är föränderliga (mutable). Exempelvis är följande giltig Python-kod:

class Car:
    number_of_wheels = 4        

    def __init__(self, make, model):
        self.make = make        
        self.model = model    

print(Car.number_of_wheels)  
car_a = Car("Volvo", "XC90")
car_a.number_of_wheels = 6
car_b = Car("Toyota", "Corolla")
print(car_a.number_of_wheels)  
print(car_b.number_of_wheels)  
4
6
4

Värdet på number_of_wheels ändras enbart för car_a i ovan exempel. När vi därefter skapar en ny instans - car_b - så ser vi att värdet fortfarande är 4 då det är så det är deklarerat på klassnivå.

Metoder i klasser

Metoder är som tidigare nämnt funktioner definierade inom en klass och som används för att definiera objekts beteenden. Precis som attribut kan metoder vara av typen instansmetoder eller klassmetoder.

  • Instansmetoder:
    Dessa kräver en instans av klassen för att kunna anropas och arbetar med data som är specifikt för den instansen. Exempelvis kan vi skapa en metod som skriver ut information om instansen enligt:

      class Car:
          number_of_wheels = 4  
    
          def __init__(self, make, model):
              self.make = make
              self.model = model
            
          def display_info(self):
              print(f"This car is a: {self.make} {self.model}")
    
      car_a = Car("Volvo", "S60")      
      car_a.display_info()
    
    This car is a: Volvo S60
  • Klassmetoder:
    Dessa metoder är istället bundna till klassen snarare än instanser av klassen. De kan därför anropas på klassnivå och har tillgång till eventuella klassattribut men inte till instansattribut. Exempelvis skulle vi från ett tidigare exempel ha tillgång till attributet number_of_wheels men inte make i en klassmetod.

      class Car:
          number_of_wheels = 4
          number_of_cars_created = 0  
    
          def __init__(self, make, model):
              self.make = make
              self.model = model
              number_of_cars_created += 1
            
          def display_info(self):
              print(f"This car is a: {self.make} {self.model}")
            
          @classmethod
          def number_of_cars(cls):
              print(f"The number of car objects is: {cls.number_of_cars_created}")
    
      Car.number_of_cars()
      car_a = Car("Volvo", "S60")   
      car_b = Car("Toyota", "Corolla")      
      Car.number_of_cars()
    
    0
    2

cls och @classmethod

För att deklarera en klassmetod så anger man dekoratorn @classmethod över metoddeklarationen. Vi måste göra detta för att särskilja en klassmetod från en instansmetod, annars kommer Pythontolkaren inte att förstå att vi försöker deklarera funktionalitet på klassnivå.

Nyckelordet cls nyttjas istället för nyckelordet self och representerar klassen. Precis som för self så placeras detta nyckelordet i metoddeklarationen och som den första parametern. Det är detta nyckelord som tillåter oss att nå och arbeta med klassattribut eller andra andra klassmetoder.

Sammanfattning

Att förstå hur attribut och metoder fungerar i Python är grundläggande för effektiv användning av klasser i objektorienterad programmering.

Genom att dessutom kunna särskilja mellan klass- och instansspecifika komponenter kan utvecklare skapa mer organiserad och modulär kod som är lättare att underhålla och återanvända.