Aprenent Python Recorrent el camí pas a pas

36 Classe 04

Ens hem basat en la font que roman al final per comentar aquest concepte.

Aquest artícle té aquesta estructura:

0. Paràmetre self
1. Creació d'una classe
2. Mètodes dels objectes
3. Mètode `__init__`
4. Classes i variables d'objecte

Les classes i els objectes són dos dels principals aspectes de la programació orientada a objecte. Una classe és un nou tipus, mentre que un objecte és una instància de la classe.

Els objectes emmagatzemen dades fent servir variables que pertanyen a l’objecte. Anomenem camps a les variables que pertanyen a un objecte o classe. Els objectes també tenen funcionalitat a partir de funcions que pertanyen a la classe. Aquestes funcions s’anomenen mètodes de la classe. Aquesta terminologia és important, ja que ens ajuda a distingir entre classes i objectes. Col·lectivament, els camps i els mètodes es coneixen com a atributs de la classe.

Els camps poden ser de dos tipus: aquells que pertanyen a cada instància o objecte de la classe, i aquells que pertanyen a la pròpia classe. Els primers es coneixen com a variables d’instància i els segons com a variables de classe.

Les classes es creen a amb la paraula reservada class. Els camps i els mètodes de la classe es llisten a un bloc indentat.

0. El paràmetre self

Els mètodes tenen una única diferència respecte a les funcions: han de contenir un paràmetre extra. Ha d’aparèixer en a la primera posició de la llista de paràmetres, però no se li ha de passar un valor qen cridar el procediment. Pyhton se n’encarrega de passar el valor d’aquest argument quan es crida al mètode.

Aquest paràmetre es refereixa a la instància de l’objecte pròpiament i, per covenció, té com a nom self. Malgrat podem donar-li qualsevol altre nom, es desaconsella.

L'ús de `self` a Python és equivalent a l'ús del punter `self` a C++, i a la referència this de Java i C#.

Potser ens preguntem com pot Pyhton donar el valor self i perquè no ens cal fer-ho nosaltrs. Un exemple ens ho aclarirà. Diguem que disposem d’una classe anomenada MyClass i una instància de la classe anomenada MyObject. Quan cridem a un mètode d’aquest objecte com MyObject.method(arg1, arg2), aquesta crida es converteix automàticament en MyClass.method(MyObject, arg1, arg2). I això és el que té d’especial el paràmetre self.

Això implica també que si tenim un mètode sense paràmetres, sempre haurem de definir el mètode amb el paràmetre self.

1. Creació d’una classe

1.1. Exemple de classe

#!/usr/bin/python
## Filename: simplestclass.py

class Person:
	pass ## Un bloc buit

p = Person()
print p

1.2. Eixida

$ python simplestclass.py
<__main__.Person instance at 0xf6fcb18c>

1.3. Explicació del funcionament

Creem una nova classe amb la paraula class seguida del nom de la classe. A continuació apareix un bloc indentat de sentències que formen el cos de la classe. En aquest cas, tenim un bloc buit que s’indica amb la sentència pass.

A continuació creem un objecte o instància d’aquesta classe fem servir el nom de la classe per un parell de parèntesi.

2. Mètodes dels objectes

2.1 Ús de mètodes

#!/usr/bin/python
## Filename: method.py

class Person:
	def sayHi(self):
		print 'Hello, how are you?'

p = Person()
p.sayHi()

## Aquest exemple també es pot escriure com Person().sayHi()

2.2. Eixida

$ python method.py
Hello, how are you?

Ací veiem self en acció. Fixem-nos que el mètode sayHi maltrat no tenir cap paràmetre, té el paràmetre self a la definició de la funció.

3. El mètode init

Hi ha alguns noms de mètode que tenen significats especials en les classes de Python. Aquest és el cas del mètode __init__.

El mètode __init__ s’executa en el moment que s’intancia cada objecte d’una classe. El mètode és útil per realitzar qualsevol inicialització que calga. Atenció amb els dos guions baixos que apareixen a ambdós costats del nom.

3.1 Ús del mètode init

#!/usr/bin/python
## Filename: class_init.py

class Person:
	def __init__(self, name):
		self.name = name
	def sayHi(self):
		print 'Hello, my name is', self.name

p = Person('Swaroop')
p.sayHi()

## Aquest exemple també es pot escriure com Person('Swaroop').sayHi()

3.2. Eixida

$ python class_init.py
Hello, my name is Swaroop

3.3. Com funciona

L’exemple defineix el mètode __init__ que rep, a banda de l’habitual self, el paràmetre name. com que el camp name coincideix amb el nom del paràmetre name, ens cal distingir-los fint servir la referència self.

Parem atenció, no fem una crida explícita explícita al mètode __init__, sinó que passem l’argument quan creem una instància de la classe. Aquesta és la principal particularitat d’aquest mètode.

Es pot veure l’ús del paràmetre self.name al mètode sayHi.

El mètode `__init__` és l'equivalent al *constructor* de C++, C## o Java.

4. Classes i variables d’objecte

Hi ha dos camps: variables de classe i variables d’objecte (o instància). La diferència està en si és la classe o l’objecte qui té la variable.

Les variables de classe són compartides en el sentit que poden ser accedides per a qualsevol objecte (instància) d’aquesta classe. Només hi ha una còpia de les variables de classe i quan qualsevol de les instàncies realitza un canvi en aquestes variables, el canvi es reflecteix també a tota la resta d’instàncies.

Les variables d’objecte pertanyen a cada objecte o instància individual. Cada objecte té la seva pròpia còpia del camp. És a dir, no estan compartides ni estan relacionades de cap manera amb el camp amb el mateix nom a una instància diferent de la mateixa classe. Estuem el següent exemple per clarificar-nos:

4.1. Ús de les variables de classe i objecte

#!/usr/bin/python
## Filename: objvar.py

class Person:
	'''Representa una persona.'''
	population = 0

	def __init__(self, name):
		'''Inicialitza les dades de persona.'''
		self.name = name
		print '(Initializing %s)' % self.name

		## Quan la persona es crea, s'afegeix a la població.
		Person.population += 1
	
	def __del__(self):
		'''Elimina la instància'''
		print '%s says bye.' % self.name

		Person.population -= 1

		if Person.population == 0:
			print 'I am the last one.'
		else:
			print 'There are still %d people left.' % Person.population
	
	def sayHi(self):
		'''Saludant.
		
		Realment això és el que fa.'''
		print 'Hi, my name is %s.' % self.name
	
	def howMany(self):
		'''Escriu la població actual.'''
		if Person.population == 1:
			print 'I am the only person here.'
		else:
			print 'We have %d persons here.' % Person.population

swaroop = Person('Swaroop')
swaroop.sayHi()
swaroop.howMany()

kalam = Person('Abdul Kalam')
kalam.sayHi()
kalam.howMany()

swaroop.sayHi()
swaroop.howMany()

4.2 Eixida

$ python objvar.py
(Initializing Swaroop)
Hi, my name is Swaroop.
I am the only person here.
(Initializing Abdul Kalam)
Hi, my name is Abdul Kalam.
We have 2 persons here.
Hi, my name is Swaroop.
We have 2 persons here.
Abdul Kalam says bye.
There are still 1 people left.
Swaroop says bye.
I am the last one.

4.3. Explicació

  1. La variable population pertany a la classe Person, per tant és una variable de classe.
  2. Fem servir el mètode __init__ per iniciar la instància de Person amb un nom.
  3. Un altre mètode especial és __del__. Aquest és cridat quan l’objecte mor. És a dir, quan no serà usat mai més i l’espai que ocupa és retornat al sistema per que puga ser reutilitzat. Equival a un destructor en C++, Java i C#.

Font: Byte of byte. Una mica de Python Swaroop C H, traducció al català de Moisés Gómez Girón. Capítol 11. Programació orientada a objectes.