POO

Propriété : exercices

Une classe Point

Définir une classe Point.

  • On pourra définir un point sous la forme p = Point(2,3) où (2,3) est le couple des coordonnées cartésiennes du point.
  • On aura accès à l'abscisse du point par p.x, l'ordonnée par p.y, le rayon polaire (distance du point à l'origine O du repère) par p.r et l'angle polaire (angle orienté entre le premier vecteur de la base et le vecteur \( \overrightarrow{Op} \) ) par p.theta.

Pour simplifier, on posera p.theta = 0 pour le point p de coordonnées cartésiennes (0,0).

  • Un code
  • Un autre code
  • Créer à partir de la forme polaire

from math import sqrt, atan2, pi, cos, sin

class Point:
	
	def __init__(self, abscisse = 0, ordonnee = 0):
		self.x = abscisse
		self.y = ordonnee
		 
	@property
	def r(self):
		return sqrt(self.x**2 + self.y**2)
		
	@property
	def theta(self):
		if self.x == 0 and self.y == 0:
			return 0
		else:
			return atan2(self.y,self.x) 
			
	@r.setter
	def r(self, nvRayon):
		angle = self.theta
		self.x = nvRayon * cos(angle)
		self.y = nvRayon * sin(angle)
		
	@theta.setter
	def theta(self, nvTheta): 
		rayon = self.r
		self.x = rayon * cos(nvTheta)
		self.y = rayon * sin(nvTheta)
		
		
	def __str__(self):
		ch = "Le point a pour coordonnées cartésiennes ({}, {}).\n".format(self.x, self.y)
		ch += "Rayon polaire : {}.\n".format(self.r)
		if not(self.x == 0 and self.y == 0):
			ch += "Angle polaire (en degrés) : {}.".format(self.theta * 180/pi)
		return ch
			
	
print("Définition d'un point de coordonnées cartésiennes (1,1).")		
p = Point(1,1)
print(p)


print("\nNouveau rayon : 2")
p.r = 2
print(p)


print("\nNouvel angle polaire : 9O degrés.")
p.theta = pi/2
print(p)


print("\nNouvelles coordonnées cartésiennes : (2,0).")
p.x, p.y = 2, 0
print(p)

from math import sqrt, atan2, pi, cos, sin

class Point:
	
	def __init__(self, abscisse = 0, ordonnee = 0):
		self._x = abscisse
		self._y = ordonnee
		self._r = sqrt(abscisse**2 + ordonnee**2)
		self._theta = atan2(abscisse,ordonnee) if not(abscisse == 0 and ordonnee == 0) else 0
		 
		 
		 
	@property
	def x(self):
		return self._x 
		
	@property
	def y(self):
		return self._y
		
	@property
	def r(self):
		return self._r
		  
	@property
	def theta(self):
		return self._theta
		
			
	@x.setter
	def x(self, nvAbs):
		self._x = nvAbs
		self._r = sqrt(nvAbs**2 + self._y**2)
		if nvAbs == 0 and self._y == 0:
			self._theta = 0
		else:
			self._theta = atan2(self._y,nvAbs) 
			
			
	@y.setter
	def y(self, nvOrd):
		self._y = nvOrd
		self._r = sqrt(self._x**2 + nvOrd**2)
		if self._x == 0 and nvOrd == 0:
			self._theta = 0
		else:
			self._theta = atan2(nvOrd,self._x) 
			
	@r.setter
	def r(self, nvRayon):
		self._r = nvRayon
		angle = self._theta
		self._x = nvRayon * cos(angle)
		self._y = nvRayon * sin(angle)
		
	@theta.setter
	def theta(self, nvTheta): 
		self._theta = nvTheta
		rayon = self._r
		self._x = rayon * cos(nvTheta)
		self._y = rayon * sin(nvTheta)
		
		
	def __str__(self):
		ch = "Le point a pour coordonnées cartésiennes ({}, {}).\n".format(self.x, self.y)
		ch += "Rayon polaire : {}.\n".format(self.r)
		if not(self.x == 0 and self.y == 0):
			ch += "Angle polaire (en degrés) : {}.".format(self.theta * 180/pi)
		return ch
			
			
			
print("Définition d'un point de coordonnées cartésiennes (1,1).")		
p = Point(1,1)
print(p)


print("\nNouveau rayon : 2")
p.r = 2
print(p)


print("\nNouvel angle polaire : 9O degrés.")
p.theta = pi/2
print(p)


print("\nNouvelles coordonnées cartésiennes : (2,0).")
p.x, p.y = 2, 0
print(p)

Dans le code précédent, on est obligé de créer le point à partir de ses coordonnées cartésiennes.

Pour pouvoir créer les points à partir des coordonnées polaires ou des coordonnées cartésiennes, on peut utiliser une méthode statique (voir cette page) comme dans le code suivant:


from math import sqrt, atan2, pi, cos, sin

class Point:

	def __init__(self, abscisse = 0, ordonnee = 0):
		self._x = abscisse
		self._y = ordonnee
		self._r = sqrt(abscisse**2 + ordonnee**2)
		self._theta = atan2(abscisse,ordonnee) if not(abscisse == 0 and ordonnee == 0) else 0
		
		
	@staticmethod
	def formeCartesienne(abscisse, ordonnee):
		return Point(abscisse, ordonnee)
		
	@staticmethod
	def formePolaire(rayon, angle):
		return Point( rayon * cos(angle), rayon * sin(angle) )



	@property
	def x(self):
		return self._x

	@property
	def y(self):
		return self._y

	@property
	def r(self):
		return self._r

	@property
	def theta(self):
		return self._theta


	@x.setter
	def x(self, nvAbs):
		self._x = nvAbs
		self._r = sqrt(nvAbs**2 + self._y**2)
		if nvAbs == 0 and self._y == 0:
			self._theta = 0
		else:
			self._theta = atan2(self._y,nvAbs)


	@y.setter
	def y(self, nvOrd):
		self._y = nvOrd
		self._r = sqrt(self._x**2 + nvOrd**2)
		if self._x == 0 and nvOrd == 0:
			self._theta = 0
		else:
			self._theta = atan2(nvOrd,self._x)

	@r.setter
	def r(self, nvRayon):
		self._r = nvRayon
		angle = self._theta
		self._x = nvRayon * cos(angle)
		self._y = nvRayon * sin(angle)

	@theta.setter
	def theta(self, nvTheta):
		self._theta = nvTheta
		rayon = self._r
		self._x = rayon * cos(nvTheta)
		self._y = rayon * sin(nvTheta)


	def __str__(self):
		ch = "Le point a pour coordonnées cartésiennes ({}, {}).\n".format(self.x, self.y)
		ch += "Rayon polaire : {}.\n".format(self.r)
		if not(self.x == 0 and self.y == 0):
			ch += "Angle polaire (en degrés) : {}.".format(self.theta * 180/pi)
		return ch



print("Définition d'un point de coordonnées cartésiennes (1,1).")
p = Point.formeCartesienne(1,1)
print(p)


print("\nNouveau rayon : 2")
p.r = 2
print(p)


print("\nNouvel angle polaire : 9O degrés.")
p.theta = pi/2
print(p)


print("\nNouvelles coordonnées cartésiennes : (2,0).")
p.x, p.y = 2, 0
print(p)

print()
print("########################################################################")
print("Définition d'un point de coordonnées polaires (2, pi/4).")
p = Point.formePolaire(2,pi/4)
print(p)


print("\nNouveau rayon : 1")
p.r = 1
print(p)


print("\nNouvel angle polaire : 9O degrés.")
p.theta = pi/2
print(p)


print("\nNouvelles coordonnées cartésiennes : (2,0).")
p.x, p.y = 2, 0
print(p)

On obtient l'affichage suivant:

Définition d'un point de coordonnées cartésiennes (1,1).
Le point a pour coordonnées cartésiennes (1, 1).
Rayon polaire : 1.4142135623730951.
Angle polaire (en degrés) : 45.0.

Nouveau rayon : 2
Le point a pour coordonnées cartésiennes (1.4142135623730951, 1.414213562373095).
Rayon polaire : 2.
Angle polaire (en degrés) : 45.0.

Nouvel angle polaire : 9O degrés.
Le point a pour coordonnées cartésiennes (1.2246467991473532e-16, 2.0).
Rayon polaire : 2.
Angle polaire (en degrés) : 90.0.

Nouvelles coordonnées cartésiennes : (2,0).
Le point a pour coordonnées cartésiennes (2, 0).
Rayon polaire : 2.0.
Angle polaire (en degrés) : 0.0.

########################################################################
Définition d'un point de coordonnées polaires (2, pi/4).
Le point a pour coordonnées cartésiennes (1.4142135623730951, 1.414213562373095).
Rayon polaire : 2.0.
Angle polaire (en degrés) : 45.00000000000001.

Nouveau rayon : 1
Le point a pour coordonnées cartésiennes (0.7071067811865475, 0.7071067811865476).
Rayon polaire : 1.
Angle polaire (en degrés) : 45.00000000000001.

Nouvel angle polaire : 9O degrés.
Le point a pour coordonnées cartésiennes (6.123233995736766e-17, 1.0).
Rayon polaire : 1.
Angle polaire (en degrés) : 90.0.

Nouvelles coordonnées cartésiennes : (2,0).
Le point a pour coordonnées cartésiennes (2, 0).
Rayon polaire : 2.0.
Angle polaire (en degrés) : 0.0.

On peut même chercher à interdire de créer une instance par a = Point(1,2):


from math import sqrt, atan2, pi, cos, sin
from random import randint

class Point:
	
	__clef = randint(1, 1000)

	def __init__(self, abscisse = 0, ordonnee = 0, clef=''):
		if clef == Point.__clef:
			self._x = abscisse
			self._y = ordonnee
			self._r = sqrt(abscisse**2 + ordonnee**2)
			self._theta = atan2(abscisse,ordonnee) if not(abscisse == 0 and ordonnee == 0) else 0
		else:
			raise RuntimeError('Utilisez Point.formePolaire() ou Point.formeCartesienne.')
		
		
	@staticmethod
	def formeCartesienne(abscisse, ordonnee):
		return Point(abscisse, ordonnee, Point.__clef)
		
	@staticmethod
	def formePolaire(rayon, angle):
		return Point( rayon * cos(angle), rayon * sin(angle), Point.__clef )



	@property
	def x(self):
		return self._x

	@property
	def y(self):
		return self._y

	@property
	def r(self):
		return self._r

	@property
	def theta(self):
		return self._theta


	@x.setter
	def x(self, nvAbs):
		self._x = nvAbs
		self._r = sqrt(nvAbs**2 + self._y**2)
		if nvAbs == 0 and self._y == 0:
			self._theta = 0
		else:
			self._theta = atan2(self._y,nvAbs)


	@y.setter
	def y(self, nvOrd):
		self._y = nvOrd
		self._r = sqrt(self._x**2 + nvOrd**2)
		if self._x == 0 and nvOrd == 0:
			self._theta = 0
		else:
			self._theta = atan2(nvOrd,self._x)

	@r.setter
	def r(self, nvRayon):
		self._r = nvRayon
		angle = self._theta
		self._x = nvRayon * cos(angle)
		self._y = nvRayon * sin(angle)

	@theta.setter
	def theta(self, nvTheta):
		self._theta = nvTheta
		rayon = self._r
		self._x = rayon * cos(nvTheta)
		self._y = rayon * sin(nvTheta)


	def __str__(self):
		ch = "Le point a pour coordonnées cartésiennes ({}, {}).\n".format(self.x, self.y)
		ch += "Rayon polaire : {}.\n".format(self.r)
		if not(self.x == 0 and self.y == 0):
			ch += "Angle polaire (en degrés) : {}.".format(self.theta * 180/pi)
		return ch



print("Définition d'un point de coordonnées cartésiennes (1,1).")
p = Point.formeCartesienne(1,1)
print(p)


print("\nNouveau rayon : 2")
p.r = 2
print(p)


print("\nNouvel angle polaire : 9O degrés.")
p.theta = pi/2
print(p)


print("\nNouvelles coordonnées cartésiennes : (2,0).")
p.x, p.y = 2, 0
print(p)

print()
print("########################################################################")
print("Définition d'un point de coordonnées polaires (2, pi/4).")
p = Point.formePolaire(2,pi/4)
print(p)


print("\nNouveau rayon : 1")
p.r = 1
print(p)


print("\nNouvel angle polaire : 9O degrés.")
p.theta = pi/2
print(p)


print("\nNouvelles coordonnées cartésiennes : (2,0).")
p.x, p.y = 2, 0
print(p)

Une classe Rationnel

On considère la classe Rationnel ci-dessous :


from math import gcd

class Rationnel:

	def __init__(self, numerateur, denominateur = 1):
		self.numerateur = numerateur
		self.denominateur = denominateur

	def __add__(self, f):
		num = self.numerateur * f.denominateur + f.numerateur * self.denominateur
		den = self.denominateur * f.denominateur
		num, den = num//gcd(num, den), den//gcd(num, den)
		return Rationnel(num, den)

	def __sub__(self, f):
		num = self.numerateur * f.denominateur - f.numerateur * self.denominateur
		den = self.denominateur * f.denominateur
		num, den = num//gcd(num, den), den//gcd(num, den)
		return Rationnel(num, den)

	def __mul__(self, f):
		num = self.numerateur * f.numerateur
		den = self.denominateur * f.denominateur
		num, den = num//gcd(num, den), den//gcd(num, den)
		return Rationnel(num, den)

	def __floordiv__(self, f):
		num = self.numerateur * f.denominateur
		den = self.denominateur * f.numerateur
		num, den = num//gcd(num, den), den//gcd(num, den)
		return Rationnel(num, den)

	def __neg__(self):
		return Rationnel(-self.numerateur, self.denominateur)

	def __str__(self):
		if self.numerateur == 0:
			return str(self.numerateur)
		else:
			return str(self.numerateur) + '/' + str(self.denominateur)



p = Rationnel(2)
q = Rationnel(3,4)
print(p+q)
print(p-q)
print(q-p)
print(p*q)
print(p//q)

print( -Rationnel(2,3))
print( -Rationnel(-2,3))
print( -Rationnel(2,-3))
print( -Rationnel(2,3) + Rationnel(2,3) )

On aimerait que le programmeur utilisateur de cette classe puisse continuer à entrer des rationnels avec un dénominateur négatif (par exemple Rationnel(3, -4)) mais qu'en interne la classe ne manipule (et ne renvoie) que des rationnels où seul le numérateur puisse être négatif.

Donner un exemple de code.

  • Un code possible

from math import gcd

class Rationnel:

	def __init__(self, numerateur, denominateur = 1):
		if denominateur < 0:
			self._numerateur = - numerateur
			self._denominateur = - denominateur
		else:
			self._numerateur = numerateur
			self._denominateur = denominateur



	@property
	def numerateur(self):
		return self._numerateur
		
	@property
	def denominateur(self):
		return self._denominateur
		
	@numerateur.setter
	def numerateur(self, den):
		self._numerateur = den
		
	@denominateur.setter
	def denominateur(self, num):
		if num < 0 :
			self._numerateur =  - self._numerateur
			self._denominateur = - num
		else:
			self._denominateur = num
			
			
	def __add__(self, f):
		num = self._numerateur * f._denominateur + f._numerateur * self._denominateur
		den = self._denominateur * f._denominateur
		num, den = num//gcd(num, den), den//gcd(num, den)
		return Rationnel(num, den)

	def __sub__(self, f):
		num = self._numerateur * f._denominateur - f._numerateur * self._denominateur
		den = self._denominateur * f._denominateur
		num, den = num//gcd(num, den), den//gcd(num, den)
		return Rationnel(num, den)

	def __mul__(self, f):
		num = self._numerateur * f._numerateur
		den = self._denominateur * f._denominateur
		num, den = num//gcd(num, den), den//gcd(num, den)
		return Rationnel(num, den)

	def __floordiv__(self, f):
		num = self._numerateur * f._denominateur
		den = self._denominateur * f._numerateur
		num, den = num//gcd(num, den), den//gcd(num, den)
		return Rationnel(num, den)

	def __neg__(self):
		return Rationnel(-self._numerateur, self._denominateur)

	def __str__(self):
		if self._numerateur == 0 or self._denominateur == 1:
			return str(self._numerateur)
		else:
			return str(self._numerateur) + '/' + str(self._denominateur)



p =  Rationnel(3,-4)
print(p)
q = Rationnel(-3,4)
print(q)
r =  Rationnel(-3,-4)
print(r)
print(p+q)
print(p*q)

a = Rationnel(4,5)
b = Rationnel(3,2)
print(-a+b)

a.numerateur = 7
a.denominateur = -6
print(a.numerateur, a.denominateur)

b.numerateur = -4
b.denominateur = -7
print(b)