Python – objektorienteret

Reklameannoncer

Python har været et objektorienteret sprog, siden det eksisterede. På grund af dette er det ligefrem nemt at oprette og bruge klasser og objekter. Dette kapitel hjælper dig med at blive ekspert i at bruge Pythons objektorienterede programmeringsstøtte.

Hvis du ikke har nogen tidligere erfaring med objektorienteret (OO) programmering, kan du med fordel konsultere et introduktionskursus om det eller i det mindste en tutorial af en eller anden art, så du har styr på de grundlæggende begreber.

Her er dog en lille introduktion til objektorienteret programmering (OOP), så du kan komme i gang –

Overblik over OOP-terminologi

  • Klasse – En brugerdefineret prototype for et objekt, der definerer et sæt attributter, som karakteriserer ethvert objekt i klassen. Attributterne er datamedlemmer (klassevariabler og instansvariabler) og metoder, som der er adgang til via punktnotation.

  • Klassevariabel – En variabel, der deles af alle instanser af en klasse. Klassevariabler defineres inden for en klasse, men uden for nogen af klassens metoder. Klassevariabler anvendes ikke så hyppigt som instansvariabler.

  • Datamedlem – En klassevariabel eller instansvariabel, der indeholder data, der er forbundet med en klasse og dens objekter.

  • Funktionsoverbelastning – Tildeling af mere end én adfærd til en bestemt funktion. Den udførte operation varierer alt efter de involverede typer objekter eller argumenter.

  • Instancevariabel – En variabel, der er defineret inde i en metode og kun tilhører den aktuelle instans af en klasse.

  • Arv – Overførsel af en klasses egenskaber til andre klasser, der er afledt af den.

  • Instans – Et individuelt objekt af en bestemt klasse. Et objekt obj, der tilhører en klasse Circle, er f.eks. en instans af klassen Circle.

  • Instantiering – Oprettelse af en instans af en klasse.

  • Metode – En særlig form for funktion, der er defineret i en klassedefinition.

  • Objekt – En unik instans af en datastruktur, der er defineret af dens klasse. Et objekt omfatter både datamedlemmer (klassevariabler og instansvariabler) og metoder.

  • Operatoroverbelastning – Tildeling af mere end én funktion til en bestemt operatør.

Skabelse af klasser

Med class-erklæringen oprettes en ny klassedefinition. Klassens navn følger umiddelbart efter nøgleordet class efterfulgt af et kolon som følger –

class ClassName: 'Optional class documentation string' class_suite
  • Klassen har en dokumentationsstreng, som kan tilgås via ClassName.__doc__.

  • Klasse_suite består af alle de komponentangivelser, der definerer klassens medlemmer, dataattributter og funktioner.

Eksempel

Følgende er eksemplet på en simpel Python-klasse –

class Employee: 'Common base class for all employees' empCount = 0 def __init__(self, name, salary): self.name = name self.salary = salary Employee.empCount += 1 def displayCount(self): print "Total Employee %d" % Employee.empCount def displayEmployee(self): print "Name : ", self.name, ", Salary: ", self.salary
  • Variablen empCount er en klassevariabel, hvis værdi deles mellem alle instanser af en denne klasse. Der kan tilgås til den som Employee.empCount inde fra klassen eller uden for klassen.

  • Den første metode __init__() er en særlig metode, som kaldes klassekonstruktør eller initialiseringsmetode, som Python kalder, når du opretter en ny instans af denne klasse.

  • Du erklærer andre klassemetoder som normale funktioner med den undtagelse, at det første argument til hver metode er self. Python tilføjer argumentet self til listen for dig; du behøver ikke at medtage det, når du kalder metoderne.

Skabelse af instansobjekter

For at oprette instanser af en klasse kalder du klassen ved hjælp af class name og indsender de argumenter, som dens __init__-metode accepterer.

"This would create first object of Employee class"emp1 = Employee("Zara", 2000)"This would create second object of Employee class"emp2 = Employee("Manni", 5000)

Accessing Attributes

Du får adgang til objektets attributter ved hjælp af dot-operatoren med object. Klassevariabel vil man få adgang til ved hjælp af klassens navn som følger –

emp1.displayEmployee()emp2.displayEmployee()print "Total Employee %d" % Employee.empCount

Nu samler vi alle begreberne –

#!/usr/bin/pythonclass Employee: 'Common base class for all employees' empCount = 0 def __init__(self, name, salary): self.name = name self.salary = salary Employee.empCount += 1 def displayCount(self): print "Total Employee %d" % Employee.empCount def displayEmployee(self): print "Name : ", self.name, ", Salary: ", self.salary"This would create first object of Employee class"emp1 = Employee("Zara", 2000)"This would create second object of Employee class"emp2 = Employee("Manni", 5000)emp1.displayEmployee()emp2.displayEmployee()print "Total Employee %d" % Employee.empCount

Når ovenstående kode udføres, giver det følgende resultat –

Name : Zara ,Salary: 2000Name : Manni ,Salary: 5000Total Employee 2

Du kan tilføje, fjerne, eller ændre attributter for klasser og objekter til enhver tid –

emp1.age = 7 # Add an 'age' attribute.emp1.age = 8 # Modify 'age' attribute.del emp1.age # Delete 'age' attribute.

I stedet for at bruge de normale instruktioner til at få adgang til attributter, kan du bruge følgende funktioner –

  • Getattr(obj, name) – til at få adgang til objektets attribut.

  • The hasattr(obj,name) – for at kontrollere, om en attribut findes eller ej.

  • The setattr(obj,name,value) – for at indstille en attribut. Hvis attributten ikke findes, vil den blive oprettet.

  • Den delattr(obj, name) – for at slette en attribut.

hasattr(emp1, 'age') # Returns true if 'age' attribute existsgetattr(emp1, 'age') # Returns value of 'age' attributesetattr(emp1, 'age', 8) # Set attribute 'age' at 8delattr(empl, 'age') # Delete attribute 'age'

Inbyggede klasseattributter

Alle Python-klasser har følgende indbyggede attributter, og der kan tilgås dem ved hjælp af dot-operatoren som enhver anden attribut –

  • __dict__ – ordbog, der indeholder klassens namespace.

  • __doc__ – streng til klassens dokumentation eller ingen, hvis den er udefineret.

  • __name____ – Klassens navn.

  • __module____ – Modulnavn, hvori klassen er defineret. Denne attribut er “__main__” i interaktiv tilstand.

  • __bases__ – En muligvis tom tupel, der indeholder basisklasserne i den rækkefølge, de forekommer i listen over basisklasser.

For ovenstående klasse lad os prøve at få adgang til alle disse attributter –

#!/usr/bin/pythonclass Employee: 'Common base class for all employees' empCount = 0 def __init__(self, name, salary): self.name = name self.salary = salary Employee.empCount += 1 def displayCount(self): print "Total Employee %d" % Employee.empCount def displayEmployee(self): print "Name : ", self.name, ", Salary: ", self.salaryprint "Employee.__doc__:", Employee.__doc__print "Employee.__name__:", Employee.__name__print "Employee.__module__:", Employee.__module__print "Employee.__bases__:", Employee.__bases__print "Employee.__dict__:", Employee.__dict__

Når ovenstående kode udføres, giver den følgende resultat –

Employee.__doc__: Common base class for all employeesEmployee.__name__: EmployeeEmployee.__module__: __main__Employee.__bases__: ()Employee.__dict__: {'__module__': '__main__', 'displayCount':<function displayCount at 0xb7c84994>, 'empCount': 2, 'displayEmployee': <function displayEmployee at 0xb7c8441c>, '__doc__': 'Common base class for all employees', '__init__': <function __init__ at 0xb7c846bc>}

Destruktion af objekter (Garbage Collection)

Python sletter automatisk unødvendige objekter (indbyggede typer eller klasseinstanser) for at frigøre plads i hukommelsen. Den proces, hvorved Python med jævne mellemrum genindvinder blokke af hukommelse, der ikke længere er i brug, kaldes Garbage Collection.

Pythons garbage collector kører under programudførelsen og udløses, når et objekts referencetælling når nul. Et objekts referencetal ændres i takt med, at antallet af aliaser, der peger på det, ændres.

Et objekts referencetal øges, når det tildeles et nyt navn eller placeres i en container (liste, tupel eller ordbog). Objektets referencetælling falder, når det slettes med del, dets reference tildeles på ny, eller dets reference går ud af rækkevidde. Når et objekts referencetal når nul, indsamler Python det automatisk.

a = 40 # Create object <40>b = a # Increase ref. count of <40> c = # Increase ref. count of <40> del a # Decrease ref. count of <40>b = 100 # Decrease ref. count of <40> c = -1 # Decrease ref. count of <40> 

Du vil normalt ikke bemærke, når garbage collector ødelægger en forældreløs instans og genvinder dens plads. Men en klasse kan implementere den særlige metode __del__(), kaldet en destruktor, som påkaldes, når instansen er ved at blive destrueret. Denne metode kan bruges til at rydde op i eventuelle ikke-hukommelsesressourcer, der anvendes af en instans.

Eksempel

Denne __del__() destructor udskriver klassens navn på en instans, der er ved at blive ødelagt –

#!/usr/bin/pythonclass Point: def __init__( self, x=0, y=0): self.x = x self.y = y def __del__(self): class_name = self.__class__.__name__ print class_name, "destroyed"pt1 = Point()pt2 = pt1pt3 = pt1print id(pt1), id(pt2), id(pt3) # prints the ids of the obejctsdel pt1del pt2del pt3

Når ovenstående kode udføres, giver den følgende resultat –

3083401324 3083401324 3083401324Point destroyed

Note – Ideelt set bør du definere dine klasser i en separat fil, hvorefter du bør importere dem i din hovedprogramfil ved hjælp af import-erklæringen.

Klassearvning

I stedet for at starte helt forfra kan du oprette en klasse ved at aflede den fra en allerede eksisterende klasse ved at angive den overordnede klasse i parentes efter det nye klassens navn.

Den underordnede klasse arver attributterne fra den overordnede klasse, og du kan bruge disse attributter, som om de var defineret i den underordnede klasse. En underklasse kan også overskrive datamedlemmer og metoder fra den overordnede klasse.

Syntaks

Afledte klasser er deklareret på samme måde som deres overordnede klasse; dog gives en liste over basisklasser at arve fra efter klassens navn –

class SubClassName (ParentClass1): 'Optional class documentation string' class_suite

Eksempel

#!/usr/bin/pythonclass Parent: # define parent class parentAttr = 100 def __init__(self): print "Calling parent constructor" def parentMethod(self): print 'Calling parent method' def setAttr(self, attr): Parent.parentAttr = attr def getAttr(self): print "Parent attribute :", Parent.parentAttrclass Child(Parent): # define child class def __init__(self): print "Calling child constructor" def childMethod(self): print 'Calling child method'c = Child() # instance of childc.childMethod() # child calls its methodc.parentMethod() # calls parent's methodc.setAttr(200) # again call parent's methodc.getAttr() # again call parent's method

Når ovenstående kode udføres, giver det følgende resultat –

Calling child constructorCalling child methodCalling parent methodParent attribute : 200

Sådan kan du køre en klasse fra flere overordnede klasser på følgende måde –

class A: # define your class A.....class B: # define your class B.....class C(A, B): # subclass of A and B.....

Du kan bruge issubclass() eller isinstance() funktionerne til at kontrollere et forhold mellem to klasser og instanser.

  • Den boolske funktion issubclass(sub, sup) returnerer sandt, hvis den givne underklasse sub faktisk er en underklasse af overklassen sup.

  • Den boolske funktion isinstance(obj, Class) returnerer sandt, hvis obj er en instans af klassen Class eller er en instans af en underklasse af Class

Overriding Methods

Du kan altid overskrive dine overordnede klassemetoder. En af grundene til at overskrive forældrenes metoder er, at du måske ønsker særlig eller anderledes funktionalitet i din underklasse.

Eksempel

#!/usr/bin/pythonclass Parent: # define parent class def myMethod(self): print 'Calling parent method'class Child(Parent): # define child class def myMethod(self): print 'Calling child method'c = Child() # instance of childc.myMethod() # child calls overridden method

Når ovenstående kode udføres, giver det følgende resultat –

Calling child method

Base Overloading Methods

Følgende tabel viser nogle generiske funktioner, som du kan overskrive i dine egne klasser –

Sr.Nr. Metode, Beskrivelse & Eksempelopkald
1

__init__ ( self )

Konstruktør (med eventuelle valgfrie argumenter)

Eksempelopkald : obj = className(args)

2

__del__( self )

Destructor, sletter et objekt

Sample Call : del obj

3

__repr__( self )

Evaluerbar strengrepræsentation

Eksempelopkald : repr(obj)

4

__str__( self )

Udskrivbar string-repræsentation

Stikprøveopkald : str(obj)

5

__cmp__ ( self, x )

Objekt sammenligning

Stikprøveopkald : cmp(obj, x)

Overbelastning af operatorer

Sæt, at du har oprettet en Vector-klasse til at repræsentere todimensionale vektorer, hvad sker der så, når du bruger plus-operatoren til at addere dem? Python vil højst sandsynligt råbe dig op.

Du kunne dog definere __add__-metoden i din klasse til at udføre vektoraddition, og så ville plusoperatoren opføre sig som forventet –

Eksempel

#!/usr/bin/pythonclass Vector: def __init__(self, a, b): self.a = a self.b = b def __str__(self): return 'Vector (%d, %d)' % (self.a, self.b) def __add__(self,other): return Vector(self.a + other.a, self.b + other.b)v1 = Vector(2,10)v2 = Vector(5,-2)print v1 + v2

Når ovenstående kode udføres, giver den følgende resultat –

Vector(7,8)

Data Hiding

Et objekts attributter kan eller kan ikke være synlige uden for klassedefinitionen. Du skal navngive attributter med et præfiks med dobbelt understregning, og disse attributter er så ikke direkte synlige for udenforstående.

Eksempel

#!/usr/bin/pythonclass JustCounter: __secretCount = 0 def count(self): self.__secretCount += 1 print self.__secretCountcounter = JustCounter()counter.count()counter.count()print counter.__secretCount

Når ovenstående kode udføres, giver det følgende resultat –

12Traceback (most recent call last): File "test.py", line 12, in <module> print counter.__secretCountAttributeError: JustCounter instance has no attribute '__secretCount'

Python beskytter disse medlemmer ved internt at ændre navnet, så det indeholder klassens navn. Du kan få adgang til sådanne attributter som object._className__attrName. Hvis du erstatter din sidste linje som følger, virker det for dig –

.........................print counter._JustCounter__secretCount

Når ovenstående kode udføres, giver det følgende resultat –

Skriv et svar

Din e-mailadresse vil ikke blive publiceret.