Hola Habr! Les presento la traducción del artículo "Programación orientada a objetos en Python vs Java" de John Fincher.
La implementación de la programación orientada a objetos (OOP) en Java y Python es diferente. El principio de trabajar con objetos, tipos de variables y otras capacidades del lenguaje puede causar dificultades para cambiar de un idioma a otro. Este artículo, que puede ser útil tanto para los programadores de Java que desean aprender Python, como para los programadores de Python que desean aprender mejor Java, ofrece las principales similitudes y diferencias entre estos lenguajes en relación con OOP.
Más detalles - debajo del corte.
Ejemplos de clases en Python y Java
Para comenzar, implementemos la clase más simple en Python y Java para ilustrar algunas de las diferencias en estos lenguajes, y gradualmente haremos cambios en esta clase.
Imagine que tenemos la siguiente definición de la clase 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 }
El nombre del archivo Java de origen debe coincidir con el nombre de la clase almacenada en él, por lo que debemos nombrar el archivo Car.java. Cada archivo Java puede contener solo una clase pública.
La misma clase en Python se vería así:
1 class Car: 2 def __init__(self, color, model, year): 3 self.color = color 4 self.model = model 5 self.year = year
En Python, puede declarar una clase en cualquier lugar, en cualquier momento. Guarde este archivo como car.py.
Usando estas clases como base, continuamos el estudio de los componentes principales de las clases y los objetos.
Atributos de objeto
En todos los lenguajes orientados a objetos, los datos sobre un objeto se almacenan en algún lugar. Tanto en Python como en Java, estos datos se almacenan en atributos , que son variables asociadas con objetos específicos.
Una de las diferencias más significativas entre Python y Java es cómo definen los atributos de clase y objeto y cómo estos lenguajes los controlan. Algunas de estas diferencias son causadas por restricciones impuestas por los idiomas, mientras que otras están asociadas con una práctica más efectiva.
Declaración e inicialización
En Java, declaramos atributos (indicando su tipo) dentro de la clase, pero fuera de todos los métodos. Antes de usar los atributos de clase, debemos definirlos:
1 public class Car { 2 private String color; 3 private String model; 4 private int year;
En Python, declaramos y definimos atributos dentro del método de la clase init (), que es un análogo del constructor en Java:
1 def __init__(self, color, model, year): 2 self.color = color 3 self.model = model 4 self.year = year
Al especificar la palabra clave self delante del nombre de la variable, le decimos a Python que estos son atributos. Cada instancia de la clase obtiene su copia. Todas las variables en Python no están mal escritas, y los atributos no son una excepción.
Las variables también se pueden crear fuera del método init (), pero esta no será la mejor solución y puede conducir a errores difíciles de detectar. Por ejemplo, puede agregar un nuevo atributo de ruedas al objeto Car de la siguiente manera:
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
Sin embargo, si olvidamos especificar la expresión my_car.wheels = 5 en la sexta línea, obtenemos un error:
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 declara una variable fuera del método, se considerará como una variable de clase. Cambiemos la clase de coche:
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
Ahora el uso de las ruedas variables cambiará. En lugar de acceder a él a través de un objeto, accedemos a él utilizando el nombre de la clase:
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
Nota: en Python, se accede a una variable de clase utilizando la siguiente sintaxis:
- El nombre del archivo que contiene la clase (sin la extensión .py)
- Punto
- Nombre de la clase
- Punto
- Nombre variable
Como guardamos la clase Car en el archivo car.py, nos referimos a la variable de clase de ruedas en la sexta línea de esta manera: car.Car.wheels.
Al trabajar con la variable de ruedas, debe prestar atención al hecho de que cambiar el valor de una variable de instancia de la clase my_car.wheels no conduce a cambiar la variable de la clase 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 >>>
En las líneas 2 y 3, definimos dos objetos Car: my_car y my_other_car.
Primero, la propiedad de las ruedas de ambos objetos es cero. En la línea 16, establecemos la variable de clase: car.Car.wheels = 4, ambos objetos ahora tienen 4 ruedas. Sin embargo, cuando en la línea 24 cambiamos la propiedad del objeto my_car.wheels = 5, la propiedad del segundo objeto permanece intacta.
Esto significa que ahora tenemos dos copias diferentes del atributo de ruedas:
- Variable de clase que se aplica a todos los objetos Car
- Una variable de instancia de clase específica que se aplica solo al objeto my_car.
Debido a esto, puede referirse accidentalmente a la instancia incorrecta y cometer un error sutil.
En Java, el equivalente de un atributo de clase es un atributo estático:
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; } }
Usualmente accedemos a variables estáticas en Java a través del nombre de la clase. Puede acceder a ellos a través de una instancia de la clase, como en Python, pero esta no será la mejor solución.
Nuestra clase de Java está empezando a alargarse. Una de las razones por las que Java es "detallado" para Python es la noción de métodos y atributos públicos y privados.
Público y privado
Java controla el acceso a los métodos y atributos al distinguir entre datos públicos y privados .
En Java, se espera que los atributos se declaren privados (o protegidos, si los descendientes de la clase necesitan acceder a ellos). Por lo tanto, restringimos el acceso a ellos desde el exterior. Para proporcionar acceso a atributos privados, declaramos métodos públicos que instalan o reciben estos datos (más sobre esto más adelante).
Recuerde que en nuestro código Java, la variable de color se declaró privada. Por lo tanto, el siguiente código no se compilará:
Car myCar = new Car("blue", "Ford", 1972);
Si no especifica el nivel de acceso a los atributos, de forma predeterminada se establecerá como paquete protegido , lo que limita el acceso a las clases dentro del paquete. Si queremos que el código anterior funcione, tendremos que hacer público el atributo.
Sin embargo, no se recomienda a Java que declare los atributos públicos. Se recomienda que los declare privados y luego utilice métodos públicos como getColor () y getModel (), como se menciona en el código anterior.
En contraste, Python carece de la noción de datos públicos y privados. En Python, todo es público. Este código de Python funcionará con una explosión:
>>> my_car = car.Car("blue", "Ford", 1972) >>>
En lugar de variables privadas en Python, existe el concepto de variables de instancia de clase no públicas ( no públicas ). Todas las variables cuyos nombres comienzan con un solo guión bajo se consideran no públicas. Esta convención de nomenclatura no nos impide acceder directamente a la variable.
Agregue la siguiente línea a nuestro auto de clase Python:
class Car: wheels = 0 def __init__(self, color, model, year): self.color = color self.model = model self.year = year self._cupholders = 6
Podemos acceder a la variable _cupholders directamente:
>>> 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 le permite acceder a dicha variable, sin embargo, algunos entornos de desarrollo como VS Code darán una advertencia:

Además, Python usa un doble guión bajo al comienzo de un nombre de variable para ocultar un atributo. Cuando Python ve dicha variable, cambia automáticamente su nombre para dificultar el acceso directo. Sin embargo, este mecanismo todavía no nos impide recurrir a él. Demostramos esto con el siguiente ejemplo:
class Car: wheels = 0 def __init__(self, color, model, year): self.color = color self.model = model self.year = year self.__cupholders = 6
Ahora, si miramos la variable __cupholders, obtenemos un error:
>>> 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'
Entonces, ¿por qué no existe el atributo __cupholders?
Aquí está la cosa. Cuando Python ve un atributo de subrayado doble al principio, lo cambia agregando un nombre de clase subrayado al principio. Para acceder al atributo directamente, también debe cambiar el nombre:
>>> print(f"It has {my_car._Car__cupholders} cupholders") It has 6 cupholders
Ahora surge la pregunta: si el atributo de la clase Java se declara privado y el atributo de la clase Python está precedido por un doble guión bajo en el nombre, entonces, ¿cómo llegar a estos datos?
Control de acceso
En Java, accedemos a atributos privados usando setters y getters . Para que el usuario repinte su máquina, agregue el siguiente código a la clase Java:
public String getColor() { return color; } public void setColor(String color) { this.color = color; }
Dado que los métodos getColor () y setColor () son públicos, cualquier usuario puede llamarlos y obtener / cambiar el color de la máquina. El uso de atributos privados, a los que accedemos a captadores y establecedores públicos, es una de las razones de la mayor "verbosidad" de Java en comparación con Python.
Como se muestra arriba, en Python podemos acceder a los atributos directamente. Como todo es público, podemos comunicarnos con cualquier cosa, en cualquier momento y en cualquier lugar. Podemos obtener y establecer valores de atributos directamente llamando por su nombre. En Python, incluso podemos eliminar atributos, lo que es 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'
Sin embargo, también sucede que queremos controlar el acceso a los atributos. En este caso, las propiedades de Python nos ayudan.
En Python, las propiedades proporcionan acceso controlado a los atributos de clase mediante decoradores. Usando propiedades, declaramos funciones en clases de Python como getters y setters en Java (eliminar atributos es una ventaja).
El funcionamiento de las propiedades se puede ver en el siguiente ejemplo de la clase Car:
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
En este ejemplo, ampliamos el concepto de la clase Car para incluir autos eléctricos. La línea 6 declara el atributo _voltage para almacenar el voltaje de la batería.
En las líneas 9 y 10 para acceso controlado, creamos la función de voltaje () y devolvemos el valor de la variable privada. Usando el decorador @property, lo convertimos en un getter, al que ahora cualquier usuario puede acceder.
En las líneas 13-15, definimos una función también llamada voltaje (). Sin embargo, lo decoramos de manera diferente: voltaje .setter. Finalmente, en las líneas 18-20, decoramos la función voltaje () con voltaje .deleter y podemos eliminar el atributo _voltaje si es necesario.
Las funciones decoradas tienen el mismo nombre, lo que indica que controlan el acceso al mismo atributo. Estos nombres de funciones también se convierten en los nombres de los atributos utilizados para obtener sus valores. Así es como funciona:
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!
Tenga en cuenta que usamos voltaje, no voltaje. Entonces le decimos a Python que aplique las propiedades que acaba de definir:
- Cuando imprimimos el valor my_car.voltage en la cuarta línea, Python llama a la función Voltage (), decorada con @property.
- Cuando asignamos el valor my_car.voltage en la 7ma línea, Python llama a la función voltaje (), decorada con voltaje .setter.
- Cuando eliminamos my_car.voltage en la línea 13, Python llama a la función voltaje (), decorada con voltaje .deleter.
Los decoradores anteriores nos dan la capacidad de controlar el acceso a los atributos sin usar varios métodos. Incluso puede hacer que el atributo sea una propiedad de solo lectura eliminando las funciones decoradas @ .setter y @ .deleter.
yo y esto
En Java, una clase se refiere a sí misma usando la palabra clave this:
public void setColor(String color) { this.color = color; }
Esto está implícito en el código Java. En principio, ni siquiera es necesario escribirlo, excepto cuando los nombres de las variables coinciden.
Setter se puede escribir así:
public void setColor(String newColor) { color = newColor; }
Como la clase Car tiene un atributo llamado color y no hay más variables con el mismo nombre en el alcance, se activa un enlace a este nombre. Utilizamos la palabra clave this en el primer ejemplo para distinguir entre un atributo y un parámetro con el mismo nombre de color.
En Python, la palabra clave self tiene un propósito similar: acceder a los miembros del atributo, pero a diferencia de Java, es obligatorio :
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 requiere que uno mismo sea obligatorio. Cada uno mismo crea o se refiere a un atributo. Si lo omitimos, Python simplemente creará una variable local en lugar de un atributo.
La diferencia en la forma en que usamos self y esto en Python y Java se debe a las principales diferencias entre los dos lenguajes y la forma en que nombran las variables y los atributos.
Métodos y funciones
La diferencia entre los lenguajes en cuestión es que en Python hay funciones, pero en Java no.
En Python, el siguiente código funcionará sin problemas (y se usa en todas partes):
>>> def say_hi(): ... print("Hi!") ... >>> say_hi() Hi!
Podemos llamar a say_hi () desde cualquier lugar en visibilidad. Esta función no contiene una referencia a sí mismo, lo que significa que es una función global, no una función de clase. No podrá cambiar ni guardar ningún dato de ninguna clase, pero puede usar variables locales y globales.
En contraste, cada línea que escribimos en Java pertenece a una clase. Una función no existe fuera de la clase y, por definición, todas las funciones de Java son métodos. En Java, lo más parecido a una función pura es un método estático:
public class Utils { static void SayHi() { System.out.println("Hi!"); } }
Utils. Se llama a SayHi () desde cualquier lugar sin crear primero una instancia de la clase Utils. Como llamamos a SayHi () sin crear un objeto, este enlace no existe. Sin embargo, esto todavía no es una función en el sentido de que say_hi () está en Python.
Herencia y polimorfismo
La herencia y el polimorfismo son dos conceptos fundamentales en OOP. Gracias al primero, los objetos reciben (en otras palabras, heredan) los atributos y la funcionalidad de otros objetos, creando una jerarquía de objetos más generales a otros más específicos. Por ejemplo, tanto la clase Car como la clase Boat son tipos específicos de la clase Vehicle. Ambos objetos heredan el comportamiento de uno o varios objetos principales. En este caso, se llaman objetos secundarios.
El polimorfismo, a su vez, es la capacidad de trabajar con diferentes objetos usando la misma función o método.
Ambos conceptos fundamentales de OOP se implementan en Java y Python de maneras completamente diferentes.
Herencia
Python admite herencia múltiple, es decir, crear una clase desde más de un padre.
Para demostrar esto, dividimos la clase Car en dos categorías: una para vehículos y otra para automóviles que utilizan electricidad:
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 clase Vehículo define los atributos de color y modelo. La clase Device tiene el atributo _voltage. La clase Car se deriva de estas dos clases, y los atributos color, modelo y _voltaje ahora forman parte de la nueva clase.
El método init () de la clase Car llama a los métodos init () de ambas clases primarias para garantizar que todos los datos se inicialicen correctamente. Después de eso, podemos agregar cualquier funcionalidad deseada a la clase Car. En este ejemplo, agregaremos el atributo year, así como el getter y setter para _voltage.
La funcionalidad de la nueva clase Car sigue siendo la misma. Podemos crear y usar objetos de clase, como hicimos algunos ejemplos anteriormente:
>>> 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
El lenguaje Java, a su vez, solo admite una única herencia, lo que significa que las clases en Java pueden heredar datos y comportamiento de una sola clase principal. Pero en Java, la herencia de múltiples interfaces es posible. Las interfaces proporcionan un grupo de métodos relacionados que deben implementarse, permitiendo que las clases secundarias se comporten de manera similar.
Para ver esto, dividimos la clase Car Java en su clase principal e interfaz:
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; } }
No olvide que cada clase y cada interfaz en Java deben colocarse en su propio archivo.
Como en el ejemplo anterior de Python, estamos creando una nueva clase de Vehículo para almacenar datos comunes y funcionalidades inherentes a los vehículos. Sin embargo, para agregar la funcionalidad del dispositivo, necesitamos crear una interfaz que defina el método para obtener el voltaje del dispositivo.
La clase Car se crea heredando de la clase Vehículo usando la palabra clave extend e implementando la interfaz del Dispositivo usando la palabra clave implements. En el constructor de la clase, llamamos al constructor padre con super (). Como solo hay una clase padre, nos referimos al constructor de la clase Vehículo. Para implementar la interfaz, redefinimos getVoltage () usando la anotación Override .
En lugar de reutilizar el código del dispositivo, como se hace en Python, Java requiere que implementemos la misma funcionalidad en cada clase que implemente la interfaz. Las interfaces solo definen métodos: no pueden definir datos de instancia de clase o detalles de implementación.
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);
:
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 (), .