Bonjour, Habr! Je vous présente la traduction de l'article «Programmation orientée objet en Python vs Java» de John Fincher.
L'implémentation de la programmation orientée objet (POO) en Java et en Python est différente. Le principe de travailler avec des objets, des types de variables et d'autres capacités linguistiques peut rendre difficile le passage d'une langue à une autre. Cet article, qui peut être utile à la fois pour les programmeurs Java qui veulent apprendre Python et pour les programmeurs Python qui veulent mieux apprendre Java, donne les principales similitudes et différences entre ces langages par rapport à la POO.
Plus de détails - sous la coupe.
Exemples de classe en Python et Java
Pour commencer, implémentons la classe la plus simple en Python et Java pour illustrer certaines des différences dans ces langages, et nous apporterons progressivement des modifications à cette classe.
Imaginez que nous ayons la définition suivante de la classe Car en Java:
1 public class Car { 2 private String color; 3 private String model; 4 private int year; 5 6 public Car(String color, String model, int year) { 7 this.color = color; 8 this.model = model; 9 this.year = year; 10 } 11 12 public String getColor() { 13 return color; 14 } 15 16 public String getModel() { 17 return model; 18 } 19 20 public int getYear() { 21 return year; 22 } 23 }
Le nom du fichier Java source doit correspondre au nom de la classe qui y est stockée, nous devons donc nommer le fichier Car.java. Chaque fichier Java ne peut contenir qu'une seule classe publique.
La même classe en Python ressemblerait à ceci:
1 class Car: 2 def __init__(self, color, model, year): 3 self.color = color 4 self.model = model 5 self.year = year
En Python, vous pouvez déclarer une classe n'importe où, n'importe quand. Enregistrez ce fichier sous car.py.
En utilisant ces classes comme base, nous poursuivons l'étude des principaux composants des classes et des objets.
Attributs d'objet
Dans tous les langages orientés objet, les données sur un objet sont stockées quelque part. En Python et en Java, ces données sont stockées dans des attributs , qui sont des variables associées à des objets spécifiques.
L'une des différences les plus importantes entre Python et Java réside dans la façon dont ils définissent les attributs de classe et d'objet et comment ces langages les contrôlent. Certaines de ces différences sont dues à des restrictions imposées par les langues, tandis que d'autres sont associées à une pratique plus efficace.
Déclaration et initialisation
En Java, nous déclarons des attributs (indiquant leur type) à l'intérieur de la classe, mais en dehors de toutes les méthodes. Avant d'utiliser des attributs de classe, nous devons les définir:
1 public class Car { 2 private String color; 3 private String model; 4 private int year;
En Python, nous déclarons et définissons des attributs à l'intérieur de la méthode de la classe init (), qui est un analogue du constructeur en Java:
1 def __init__(self, color, model, year): 2 self.color = color 3 self.model = model 4 self.year = year
En spécifiant le mot-clé self devant le nom de la variable, nous disons à Python que ce sont des attributs. Chaque instance de la classe obtient sa copie. Toutes les variables en Python ne sont pas typées de manière lâche et les attributs ne font pas exception.
Des variables peuvent également être créées en dehors de la méthode init (), mais ce ne sera pas la meilleure solution et peut conduire à des bogues difficiles à détecter. Par exemple, vous pouvez ajouter un nouvel attribut roues à l'objet Car comme suit:
1 >>> import car 2 >>> my_car = car.Car("yellow", "beetle", 1967) 3 >>> print(f"My car is {my_car.color}") 4 My car is yellow 5 6 >>> my_car.wheels = 5 7 >>> print(f"Wheels: {my_car.wheels}") 8 Wheels: 5
Cependant, si nous oublions de spécifier l'expression my_car.wheels = 5 dans la 6ème ligne, nous obtenons une erreur:
1 >>> import car 2 >>> my_car = car.Car("yellow", "beetle", 1967) 3 >>> print(f"My car is {my_car.color}") 4 My car is yellow 5 6 >>> print(f"Wheels: {my_car.wheels}") 7 Traceback (most recent call last): 8 File "<stdin>", line 1, in <module> 9 AttributeError: 'Car' object has no attribute 'wheels'
En Python, si vous déclarez une variable en dehors de la méthode, elle sera considérée comme une variable de classe. Changeons la classe de voiture:
1 class Car: 2 3 wheels = 0 4 5 def __init__(self, color, model, year): 6 self.color = color 7 self.model = model 8 self.year = year
Maintenant, l'utilisation des roues variables va changer. Au lieu d'y accéder via un objet, nous y accédons en utilisant le nom de classe:
1 >>> import car 2 >>> my_car = car.Car("yellow", "beetle", 1967) 3 >>> print(f"My car is {my_car.color}") 4 My car is yellow 5 6 >>> print(f"It has {car.Car.wheels} wheels") 7 It has 0 wheels 8 9 >>> print(f"It has {my_car.wheels} wheels") 10 It has 0 wheels
Remarque: en Python, une variable de classe est accessible à l'aide de la syntaxe suivante:
- Le nom du fichier contenant la classe (sans l'extension .py)
- Point
- Nom de classe
- Point
- Nom de variable
Puisque nous avons enregistré la classe Car dans le fichier car.py, nous nous référons à la variable de classe de roues de la 6e ligne de cette façon: car.Car.wheels.
Lorsque vous travaillez avec la variable roues, vous devez faire attention au fait que la modification de la valeur d'une variable d'instance de la classe my_car.wheels n'entraîne pas la modification de la variable de la classe car.Car.wheels:
1 >>> from car import * 2 >>> my_car = car.Car("yellow", "Beetle", "1966") 3 >>> my_other_car = car.Car("red", "corvette", "1999") 4 5 >>> print(f"My car is {my_car.color}") 6 My car is yellow 7 >>> print(f"It has {my_car.wheels} wheels") 8 It has 0 wheels 9 10 >>> print(f"My other car is {my_other_car.color}") 11 My other car is red 12 >>> print(f"It has {my_other_car.wheels} wheels") 13 It has 0 wheels 14 15 >>>
Aux lignes 2 et 3, nous avons défini deux objets Car: my_car et my_other_car.
Premièrement, la propriété roues des deux objets est nulle. Sur la 16e ligne, nous avons défini la variable de classe: car.Car.wheels = 4, les deux objets ont maintenant 4 roues. Cependant, lorsque sur la 24ème ligne nous modifions la propriété de l'objet my_car.wheels = 5, la propriété du deuxième objet reste intacte.
Cela signifie que nous avons maintenant deux copies différentes de l'attribut roues:
- Variable de classe qui s'applique à tous les objets Car
- Variable d'instance de classe spécifique qui s'applique uniquement à l'objet my_car.
Pour cette raison, vous pouvez accidentellement vous référer à la mauvaise instance et commettre une erreur subtile.
En Java, l'équivalent d'un attribut de classe est un attribut statique:
public class Car { private String color; private String model; private int year; private static int wheels; public Car(String color, String model, int year) { this.color = color; this.model = model; this.year = year; } public static int getWheels() { return wheels; } public static void setWheels(int count) { wheels = count; } }
Habituellement, nous accédons aux variables statiques en Java via le nom de classe. Vous pouvez y accéder via une instance de la classe, comme en Python, mais ce ne sera pas la meilleure solution.
Notre classe Java commence à s'allonger. L'une des raisons pour lesquelles Java est «verbeux» pour Python est la notion de méthodes et d'attributs publics et privés.
Public et privé
Java contrôle l'accès aux méthodes et aux attributs en distinguant les données publiques et privées .
En Java, il est prévu que les attributs seront déclarés privés (ou protégés, si les descendants de la classe ont besoin d'y accéder). Ainsi, nous en restreignons l'accès depuis l'extérieur. Pour fournir un accès aux attributs privés, nous déclarons des méthodes publiques qui installent ou reçoivent ces données (plus d'informations à ce sujet plus tard).
Rappelons que dans notre code Java, la variable de couleur a été déclarée privée. Par conséquent, le code ci-dessous ne se compilera pas:
Car myCar = new Car("blue", "Ford", 1972);
Si vous ne spécifiez pas le niveau d'accès aux attributs, par défaut, il sera défini comme protégé par package , ce qui limite l'accès aux classes au sein du package. Si nous voulons que le code ci-dessus fonctionne, nous devrons rendre l'attribut public.
Cependant, Java n'est pas encouragé à déclarer des attributs publics. Il est recommandé de les déclarer privés, puis d'utiliser des méthodes publiques comme getColor () et getModel (), comme mentionné dans le code ci-dessus.
En revanche, Python n'a pas la notion de données publiques et privées. En Python, tout est public. Ce code python fonctionnera avec un bang:
>>> my_car = car.Car("blue", "Ford", 1972) >>>
Au lieu de variables privées en Python, il y a le concept de variables d'instance de classe non publiques ( non publiques ). Toutes les variables dont les noms commencent par un seul trait de soulignement sont considérées comme non publiques. Cette convention de dénomination ne nous empêche pas d'accéder directement à la variable.
Ajoutez la ligne suivante à notre voiture de classe Python:
class Car: wheels = 0 def __init__(self, color, model, year): self.color = color self.model = model self.year = year self._cupholders = 6
Nous pouvons accéder directement à la variable _cupholders:
>>> import car >>> my_car = car.Car("yellow", "Beetle", "1969") >>> print(f"It was built in {my_car.year}") It was built in 1969 >>> my_car.year = 1966 >>> print(f"It was built in {my_car.year}") It was built in 1966 >>> print(f"It has {my_car._cupholders} cupholders.") It has 6 cupholders.
Python vous permet d'accéder à une telle variable, cependant, certains environnements de développement comme VS Code donneront un avertissement:

De plus, Python utilise un double soulignement au début d'un nom de variable pour masquer un attribut. Lorsque Python voit une telle variable, il change automatiquement son nom pour rendre l'accès direct difficile. Cependant, ce mécanisme ne nous empêche toujours pas d'y recourir. Nous le démontrons avec l'exemple suivant:
class Car: wheels = 0 def __init__(self, color, model, year): self.color = color self.model = model self.year = year self.__cupholders = 6
Maintenant, si nous regardons la variable __cupholders, nous obtenons une erreur:
>>> import car >>> my_car = car.Car("yellow", "Beetle", "1969") >>> print(f"It was built in {my_car.year}") It was built in 1969 >>> my_car.year = 1966 >>> print(f"It was built in {my_car.year}") It was built in 1966 >>> print(f"It has {my_car.__cupholders} cupholders.") Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: 'Car' object has no attribute '__cupholders'
Alors pourquoi l'attribut __cupholders n'existe-t-il pas?
Voici le truc. Lorsque Python voit un attribut de soulignement double au tout début, il le change en ajoutant un nom de classe souligné au début. Pour accéder directement à l'attribut, vous devez également modifier le nom:
>>> print(f"It has {my_car._Car__cupholders} cupholders") It has 6 cupholders
Maintenant, la question se pose: si l'attribut de la classe Java est déclaré privé et que l'attribut de la classe Python est précédé d'un double soulignement dans le nom, alors comment accéder à ces données?
Contrôle d'accès
En Java, nous accédons aux attributs privés à l'aide de setters et de getters . Pour que l'utilisateur puisse repeindre sa machine, ajoutez le morceau de code suivant à la classe Java:
public String getColor() { return color; } public void setColor(String color) { this.color = color; }
Étant donné que les méthodes getColor () et setColor () sont publiques, tout utilisateur peut les appeler et obtenir / modifier la couleur de la machine. L'utilisation d'attributs privés, auxquels nous accédons aux getters et setters publics, est l'une des raisons de la plus grande «verbosité» de Java par rapport à Python.
Comme indiqué ci-dessus, en Python, nous pouvons accéder directement aux attributs. Puisque tout est public, nous pouvons tendre la main à tout, n'importe quand, n'importe où. Nous pouvons obtenir et définir des valeurs d'attribut directement en appelant par leur nom. En Python, nous pouvons même supprimer des attributs, ce qui est impensable en Java:
>>> my_car = Car("yellow", "beetle", 1969) >>> print(f"My car was built in {my_car.year}") My car was built in 1969 >>> my_car.year = 1966 >>> print(f"It was built in {my_car.year}") It was built in 1966 >>> del my_car.year >>> print(f"It was built in {my_car.year}") Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: 'Car' object has no attribute 'year'
Cependant, il arrive également que nous voulions contrôler l'accès aux attributs. Dans ce cas, les propriétés Python viennent à notre aide.
En Python, les propriétés fournissent un accès contrôlé aux attributs de classe à l'aide de décorateurs. En utilisant des propriétés, nous déclarons des fonctions dans les classes Python comme les getters et setters en Java (la suppression des attributs est un bonus).
Le fonctionnement des propriétés peut être vu dans l'exemple de classe Car suivant:
1 class Car: 2 def __init__(self, color, model, year): 3 self.color = color 4 self.model = model 5 self.year = year 6 self._voltage = 12 7 8 @property 9 def voltage(self): 10 return self._voltage 11 12 @voltage.setter 13 def voltage(self, volts): 14 print("Warning: this can cause problems!") 15 self._voltage = volts 16 17 @voltage.deleter 18 def voltage(self): 19 print("Warning: the radio will stop working!") 20 del self._voltage
Dans cet exemple, nous étendons le concept de la classe Car pour inclure les voitures électriques. La ligne 6 déclare l'attribut _voltage pour y stocker la tension de la batterie.
Dans les lignes 9 et 10 pour l'accès contrôlé, nous créons la fonction voltage () et renvoyons la valeur de la variable privée. En utilisant le décorateur @property, nous le transformons en getter, auquel tout utilisateur peut désormais accéder.
Aux lignes 13 à 15, nous définissons une fonction également appelée tension (). Cependant, nous le décorons différemment: tension .setter. Enfin, dans les lignes 18-20, nous décorons la fonction voltage () avec voltage .deleter et pouvons supprimer l'attribut _voltage si nécessaire.
Les fonctions décorées ont le même nom, ce qui indique qu'elles contrôlent l'accès au même attribut. Ces noms de fonction deviennent également les noms des attributs utilisés pour obtenir leurs valeurs. Voici comment cela fonctionne:
1 >>> from car import * 2 >>> my_car = Car("yellow", "beetle", 1969) 3 4 >>> print(f"My car uses {my_car.voltage} volts") 5 My car uses 12 volts 6 7 >>> my_car.voltage = 6 8 Warning: this can cause problems! 9 10 >>> print(f"My car now uses {my_car.voltage} volts") 11 My car now uses 6 volts 12 13 >>> del my_car.voltage 14 Warning: the radio will stop working!
Veuillez noter que nous utilisons la tension, pas la tension. Nous demandons donc à Python d'appliquer les propriétés qu'il vient de définir:
- Lorsque nous imprimons la valeur my_car.voltage sur la 4ème ligne, Python appelle la fonction voltage (), décorée avec @property.
- Lorsque nous attribuons la valeur my_car.voltage à la 7e ligne, Python appelle la fonction voltage (), décorée avec voltage .setter.
- Lorsque nous supprimons my_car.voltage à la ligne 13, Python appelle la fonction voltage (), décorée avec voltage .deleter.
Les décorateurs ci-dessus nous permettent de contrôler l'accès aux attributs sans utiliser différentes méthodes. Vous pouvez même faire de l'attribut une propriété en lecture seule en supprimant les fonctions décorées @ .setter et @ .deleter.
moi et cela
En Java, une classe se réfère à elle-même en utilisant le mot-clé this:
public void setColor(String color) { this.color = color; }
cela est implicite dans le code Java. En principe, il n'est même pas nécessaire de l'écrire, sauf lorsque les noms des variables coïncident.
Setter peut être écrit comme ceci:
public void setColor(String newColor) { color = newColor; }
Étant donné que la classe Car a un attribut appelé color et qu'il n'y a plus de variables ayant le même nom dans la portée, un lien vers ce nom est déclenché. Nous avons utilisé le mot-clé this dans le premier exemple pour faire la distinction entre un attribut et un paramètre avec le même nom de couleur.
En Python, le mot clé self sert un objectif similaire: accéder aux membres d'attribut, mais contrairement à Java, il est requis :
class Car: def __init__(self, color, model, year): self.color = color self.model = model self.year = year self._voltage = 12 @property def voltage(self): return self._voltage
Python requiert que self soit obligatoire. Chaque moi crée ou fait référence à un attribut. Si nous le sautons, alors Python créera simplement une variable locale au lieu d'un attribut.
La différence dans la façon dont nous utilisons self et cela en Python et Java est due aux principales différences entre les deux langages et la façon dont ils nomment les variables et les attributs.
Méthodes et fonctions
La différence entre les langages en question est qu'en Python il y a des fonctions, mais en Java elles ne le sont pas.
En Python, le code suivant fonctionnera sans problème (et est utilisé partout):
>>> def say_hi(): ... print("Hi!") ... >>> say_hi() Hi!
Nous pouvons appeler say_hi () de n'importe où dans la visibilité. Cette fonction ne contient pas de référence à soi, ce qui signifie que c'est une fonction globale, pas une fonction de classe. Elle ne pourra ni modifier ni enregistrer les données d'une classe, mais elle pourra utiliser des variables locales et globales.
En revanche, chaque ligne que nous écrivons en Java appartient à une classe. Une fonction n'existe pas en dehors de la classe, et par définition, toutes les fonctions Java sont des méthodes. En Java, la chose la plus proche d'une fonction pure est une méthode statique:
public class Utils { static void SayHi() { System.out.println("Hi!"); } }
Utils. SayHi () est appelé de n'importe où sans créer au préalable une instance de la classe Utils. Puisque nous appelons SayHi () sans créer d'objet, ce lien n'existe pas. Cependant, ce n'est toujours pas une fonction dans le sens où say_hi () est en Python.
Hérédité et polymorphisme
L'héritage et le polymorphisme sont deux concepts fondamentaux de la POO. Grâce au premier, les objets reçoivent (en d'autres termes, héritent) les attributs et fonctionnalités d'autres objets, créant une hiérarchie d'objets plus généraux vers des objets plus spécifiques. Par exemple, la classe Car et la classe Boat sont des types spécifiques de la classe Vehicle. Les deux objets héritent du comportement d'un parent ou de plusieurs objets parents. Dans ce cas, ils sont appelés objets enfants.
Le polymorphisme, à son tour, est la capacité de travailler avec différents objets en utilisant la même fonction ou méthode.
Ces deux concepts OOP fondamentaux sont implémentés en Java et en Python de manières complètement différentes.
Héritage
Python prend en charge l'héritage multiple, c'est-à-dire la création d'une classe à partir de plusieurs parents.
Pour le démontrer, nous divisons la classe Car en deux catégories: une pour les véhicules et une pour les voitures utilisant l'électricité:
class Vehicle: def __init__(self, color, model): self.color = color self.model = model class Device: def __init__(self): self._voltage = 12 class Car(Vehicle, Device): def __init__(self, color, model, year): Vehicle.__init__(self, color, model) Device.__init__(self) self.year = year @property def voltage(self): return self._voltage @voltage.setter def voltage(self, volts): print("Warning: this can cause problems!") self._voltage = volts @voltage.deleter def voltage(self): print("Warning: the radio will stop working!") del self._voltage
La classe Vehicle définit les attributs de couleur et de modèle. La classe Device a l'attribut _voltage. La classe Car dérive de ces deux classes et les attributs color, model et _voltage font désormais partie de la nouvelle classe.
La méthode init () de la classe Car appelle les méthodes init () des deux classes parentes pour garantir que toutes les données sont correctement initialisées. Après cela, nous pouvons ajouter toutes les fonctionnalités souhaitées à la classe Car. Dans cet exemple, nous allons ajouter l'attribut year, ainsi que le getter et le setter pour _voltage.
La fonctionnalité de la nouvelle classe Car reste la même. Nous pouvons créer et utiliser des objets de classe, comme nous l'avons fait quelques exemples plus tôt:
>>> from car import * >>> my_car = Car("yellow", "beetle", 1969) >>> print(f"My car is {my_car.color}") My car is yellow >>> print(f"My car uses {my_car.voltage} volts") My car uses 12 volts >>> my_car.voltage = 6 Warning: this can cause problems! >>> print(f"My car now uses {my_car.voltage} volts") My car now uses 6 volts
Le langage Java, à son tour, ne prend en charge que l'héritage unique, ce qui signifie que les classes en Java peuvent hériter des données et du comportement d'une seule classe parente. Mais en Java, l'héritage de plusieurs interfaces est possible. Les interfaces fournissent un groupe de méthodes connexes qui doivent être implémentées, permettant aux classes enfants de se comporter de manière similaire.
Pour voir cela, nous avons divisé la classe Java Java en sa classe parent et son interface:
public class Vehicle { private String color; private String model; public Vehicle(String color, String model) { this.color = color; this.model = model; } public String getColor() { return color; } public String getModel() { return model; } } public interface Device { int getVoltage(); } public class Car extends Vehicle implements Device { private int voltage; private int year; public Car(String color, String model, int year) { super(color, model); this.year = year; this.voltage = 12; } @Override public int getVoltage() { return voltage; } public int getYear() { return year; } }
N'oubliez pas que chaque classe et chaque interface en Java doit être placée dans son propre fichier.
Comme dans l'exemple ci-dessus avec Python, nous créons une nouvelle classe Vehicle pour stocker les données et les fonctionnalités communes inhérentes aux véhicules. Cependant, pour ajouter la fonctionnalité de Device, nous devons créer une interface qui définit la méthode pour obtenir la tension de l'appareil.
La classe Car est créée en héritant de la classe Vehicle à l'aide du mot clé extend et en implémentant l'interface Device à l'aide du mot clé implements. Dans le constructeur de classe, nous appelons le constructeur parent avec super (). Puisqu'il n'y a qu'une seule classe parent, nous nous référons au constructeur de la classe Vehicle. Pour implémenter l'interface, nous redéfinissons getVoltage () à l'aide de l'annotation Override .
Au lieu de réutiliser le code de Device, comme cela se fait en Python, Java nécessite que nous implémentions la même fonctionnalité dans chaque classe qui implémente l'interface. Les interfaces ne définissent que les méthodes - elles ne peuvent pas définir les données d'instance de classe ou les détails d'implémentation.
Alors pourquoi cela se produit-il avec Java? .
Java . , Java- , , . , .
Java- charge(), Device. , Device, charge().
Rhino.java:
public class Rhino { }
Main.java charge() , Car Rhino.
public class Main{ public static void charge(Device device) { device.getVoltage(); } public static void main(String[] args) throws Exception { Car car = new Car("yellow", "beetle", 1969); Rhino rhino = new Rhino(); charge(car); charge(rhino); } }
, : Information:2019-02-02 15:20 - Compilation completed with 1 error and 0 warnings in 4 s 395 ms Main.java Error:(43, 11) java: incompatible types: Rhino cannot be converted to Device
Rhino Device, charge().
( — strict variable typing, , Python ) , Java, Python , : « , » ( : " , , , , " – . ). , Python .
Python:
>>> def charge(device): ... if hasattr(device, '_voltage'): ... print(f"Charging a {device._voltage} volt device") ... else: ... print(f"I can't charge a {device.__class__.__name__}") ... >>> class Phone(Device): ... pass ... >>> class Rhino: ... pass ... >>> my_car = Car("yellow", "Beetle", "1966") >>> my_phone = Phone() >>> my_rhino = Rhino() >>> charge(my_car) Charging a 12 volt device >>> charge(my_phone) Charging a 12 volt device >>> charge(my_rhino) I can't charge a Rhino
charge() _voltage. Device , - (Car Phone) , , , . , Device ( Rhino), , , , (rhino) .
Java Object, . , . Object :
class Object { boolean equals(Object obj) { ... } int hashCode() { ... } String toString() { ... } }
equals() , , hashCode() , . Java . , , , .
toString() . . , , , , System.out.println():
Car car = new Car("yellow", "Beetle", 1969); System.out.println(car);
car:
Car@61bbe9ba
, ? , toString(). Car:
public String toString() { return "Car: " + getColor() + " : " + getModel() + " : " + getYear(); }
, , :
Car: yellow : Beetle : 1969
Python (dunder — double underscore). Python- , , , .
Python : repr () str (). repr (), str () . hashcode() toString() Java.
Java, Python :
>>> my_car = Car("yellow", "Beetle", "1966") >>> print(repr(my_car)) <car.Car object at 0x7fe4ca154f98> >>> print(str(my_car)) <car.Car object at 0x7fe4ca154f98>
, str () Python- Car:
def __str__(self): return f'Car {self.color} : {self.model} : {self.year}'
:
>>> my_car = Car("yellow", "Beetle", "1966") >>> print(repr(my_car)) <car.Car object at 0x7f09e9a7b630> >>> print(str(my_car)) Car yellow : Beetle : 1966
. repr (), .
Python , , , .
Python . Python , Java .
Python- Car :
class Car: def __init__(self, color, model, year): self.color = color self.model = model self.year = year def __str__(self): return f'Car {self.color} : {self.model} : {self.year}' def __eq__(self, other): return self.year == other.year def __lt__(self, other): return self.year < other.year def __add__(self, other): return Car(self.color + other.color, self.model + other.model, int(self.year) + int(other.year))
, :
Python , , , .
Car:
>>> my_car = Car("yellow", "Beetle", "1966") >>> your_car = Car("red", "Corvette", "1967") >>> print (my_car < your_car) True >>> print (my_car > your_car) False >>> print (my_car == your_car) False >>> print (my_car + your_car) Car yellowred : BeetleCorvette : 3933
, , , Java.
– . Java, Python .
. Python type() isinstance () , :
>>> my_car = Car("yellow", "Beetle", "1966") >>> print(type(my_car)) <class 'car.Car'> >>> print(isinstance(my_car, Car)) True >>> print(isinstance(my_car, Device)) True
Java getClass() instanceof :
Car car = new Car("yellow", "beetle", 1969); System.out.println(car.getClass()); System.out.println(car instanceof Car);
Nous obtenons ce qui suit:
class com.realpython.Car true
Python dir() , ( ). , getattr():
>>> print(dir(my_car)) ['_Car__cupholders', '__add__', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_voltage', 'color', 'model', 'voltage', 'wheels', 'year'] >>> print(getattr(my_car, "__format__")) <built-in method __format__ of Car object at 0x7fb4c10f5438>
Java , , , .
getFields() . , Car , :
Field[] fields = car.getClass().getFields();
Java , getDeclaredMethods(). get-, , , :
1) getDeclaredMethods()
2) :
:
1 public static boolean getProperty(String name, Object object) throws Exception { 2 3 Method[] declaredMethods = object.getClass().getDeclaredMethods(); 4 for (Method method : declaredMethods) { 5 if (isGetter(method) && 6 method.getName().toUpperCase().contains(name.toUpperCase())) { 7 return true; 8 } 9 } 10 return false; 11 } 12 13
getProperty() – . . true, , false.
Java, Python .
Java- true , , . , getDeclaredMethods() Method. Method invoke(), Method. 7 true, , method.invoke(object).
Python. , Python , , :
>>> for method_name in dir(my_car): ... if callable(getattr(my_car, method_name)): ... print(method_name) ... __add__ __class__ __delattr__ __dir__ __eq__ __format__ __ge__ __getattribute__ __gt__ __init__ __init_subclass__ __le__ __lt__ __ne__ __new__ __reduce__ __reduce_ex__ __repr__ __setattr__ __sizeof__ __str__ __subclasshook__
Python , Java. str () :
>>> for method_name in dir(my_car): ... attr = getattr(my_car, method_name) ... if callable(attr): ... if method_name == '__str__': ... print(attr()) ... Car yellow : Beetle : 1966
, dir(). , getattr(), callable(), . , , str (), .