Python - Duda sobre las clases en python

 
Vista:

Duda sobre las clases en python

Publicado por Miguel (8 intervenciones) el 14/05/2018 18:51:08
Buenos días a todos.

Hace poco tiempo que entré en contacto con el lenguaje de programación Python. Voy haciendo mis pinitos de lo poco que voy aprendiendo de manera autodidacta.

El caso es que el tema de las Clases se me va atragantando desde el principio. El concepto, en términos generales, lo cogí en seguida. Pero no consigo hacerme con ellas.

Si no lo entendí mal una clase es, por decirlo de una manera sencilla, un archivador (como los de una oficina para guardar expedientes) donde en cada cajón (clase) se almacenan los expedientes (métodos y demás).

El caso es que he probado a hacer una clase y, para ser sincero, funciona correctamente (o eso me parece). Si me lo permiten, pongo aquí un extracto de la misma. La clase se llama Triangulo y está guardada en un archivo llamado triangulos.py:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
#! /usr/bin/env python3
# -*- coding:utf-8 -*-
 
import math
 
 
class Triangulo:
 
    def __init__(self, lado_1, lado_2, lado_3):
        self.lado_1 = lado_1
        self.lado_2 = lado_2
        self.lado_3 = lado_3
 
    def mayor(self):
        '''(número, número, número) -> número

        Método que comprueba que lado del triángulo es el mayor.

        Atributos:
            lado_1 --- Primer lado del triángulo.
            lado_2 --- Segundo lado del triángulo.
            lado_3 --- Tercer lado del triángulo.

        Ejemplos de uso:
            >>> mayor(3, 4, 5)
            5
        '''
 
        mayor = self.lado_1
        if self.lado_2 > mayor:
            mayor = self.lado_2
        if self.lado_3 > mayor:
            mayor = self.lado_3
        return mayor
 
    def menor(self):
        '''(número, número, número) -> número

        Método que comprueba que lado del triángulo es el menor.

        Atributos:
            lado_1 --- Primer lado del triángulo.
            lado_2 --- Segundo lado del triángulo.
            lado_3 --- Tercer lado del triángulo.

        Ejemplos de uso:
            >>> menor(3, 4, 5)
            3
        '''
 
        menor = self.lado_3
        if self.lado_2 < menor:
            menor = self.lado_2
        if self.lado_1 < menor:
            menor = self.lado_1
        return menor
 
    def mediano(self):
        '''(número, número, número) -> número

        Método que comprueba que lado del triángulo es el mediano.

        Atributos:
            lado_1 --- Primer lado del triángulo.
            lado_2 --- Segundo lado del triángulo.
            lado_3 --- Tercer lado del triángulo.

        Ejemplos de uso:
            >>> mediano(3, 4, 5)
            4
        '''
 
        if self.lado_3 > self.lado_2 and self.lado_3 < self.lado_1 or \
                self.lado_3 > self.lado_1 and self.lado_3 < self.lado_2:
            mediano = self.lado_3
        elif self.lado_2 > self.lado_3 and self.lado_2 < self.lado_1 or \
                self.lado_2 > self.lado_1 and self.lado_2 < self.lado_3:
            mediano = self.lado_2
        else:
            mediano = self.lado_1
        return mediano
 
    def comprueba_triangulo(self):
        '''(número, número, número) -> boleano

        Método que comprueba si tres segmentos dados forman un
        triángulo.

        Atributos:
            lado_1 --- Primer lado del triángulo.
            lado_2 --- Segundo lado del triángulo.
            lado_3 --- Tercer lado del triángulo.

        Ejemplos de uso:
            >>> comprueba_triangulo(3, 4, 5)
            True
        '''
 
        es_triangulo = False
        if self.lado_1 < self.lado_2 + self.lado_3 and (self.lado_1 > \
                self.lado_2 - self.lado_3 or self.lado_1 > \
                                                    self.lado_3 - self.lado_2):
            if self.lado_2 < self.lado_1 + self.lado_3 and (self.lado_2 > \
                    self.lado_1 - self.lado_3 or self.lado_2 > \
                                                    self.lado_3 - self.lado_1):
                if self.lado_3 < self.lado_2 + self.lado_1 and (self.lado_3 > \
                        self.lado_2 - self.lado_1 or self.lado_3 > \
                                                    self.lado_1 - self.lado_2):
                    es_triangulo = True
        return es_triangulo
 
    def tipo(self):
        '''(número, número, número) -> cadena

        Método que comprueba el tipo de triángulo (acutángulo, rectángulo u
        obtusángulo) que forman tres segmentos.

        Atributos:
            lado_1 --- Primer lado del triángulo.
            lado_2 --- Segundo lado del triángulo.
            lado_3 --- Tercer lado del triángulo.

        Ejemplos de uso:
            >>> tipo(3, 4, 5)
            rectángulo
        '''
 
        if self.lado_1 ** 2 == self.lado_2 ** 2 + self.lado_3 ** 2 or \
                self.lado_2 ** 2 == self.lado_1 ** 2 + self.lado_3 ** 2 or \
                self.lado_3 ** 2 == self.lado_2 ** 2 + self.lado_1 ** 2:
            tipo = 'rectángulo'
        elif self.lado_1 ** 2 < self.lado_2 ** 2 + self.lado_3 ** 2 and \
                self.lado_2 ** 2 < self.lado_1 ** 2 + self.lado_3 ** 2 and \
                self.lado_3 ** 2 < self.lado_2 ** 2 + self.lado_1 ** 2:
            tipo = 'acutángulo'
        else:
            tipo = 'obtusángulo'
        return tipo
 
    def altura_lado(self):
        '''(número, número, numero) -> tupla

        Método que calcula las 3 alturas de un triángulo.

        Atributos:
            lado_1 --- Primer lado del triángulo.
            lado_2 --- Segundo lado del triángulo.
            lado_3 --- Tercer lado del triángulo.

        Ejemplos de uso:
            >>> altura_lado(3, 4, 5)
        '''
 
        semiperimetro = (self.lado_1 + self.lado_2 + self.lado_3) / 2
        altura_1 = round((2 / self.lado_1) * math.sqrt(semiperimetro *
                         (semiperimetro - self.lado_1) *
                         (semiperimetro - self.lado_2) *
                         (semiperimetro - self.lado_3)), 2)
        altura_2 = round((2 / self.lado_2) * math.sqrt(semiperimetro *
                         (semiperimetro - self.lado_1) *
                         (semiperimetro - self.lado_2) *
                         (semiperimetro - self.lado_3)), 2)
        altura_3 = round((2 / self.lado_3) * math.sqrt(semiperimetro *
                         (semiperimetro - self.lado_1) *
                         (semiperimetro - self.lado_2) *
                         (semiperimetro - self.lado_3)), 2)
        return [altura_1, altura_2, altura_3]
 
    def angulos(self):
        '''(número, número, número) -> tupla

        Método que calcula el valor de los tres ángulos de un triángulo.

        Atributos:
            lado_1 --- Primer lado del triángulo.
            lado_2 --- Segundo lado del triángulo.
            lado_3 --- Tercer lado del triángulo.
        '''
 
        angulo_a = round(math.degrees(math.acos((self.lado_2 ** 2 +
                         self.lado_3 ** 2 - self.lado_1 ** 2) /
                         (2 * self.lado_2 * self.lado_3))), 2)
        angulo_b = round(math.degrees(math.acos((self.lado_1 ** 2 +
                         self.lado_3 ** 2 - self.lado_2 ** 2) /
                         (2 * self.lado_1 * self.lado_3))), 2)
        angulo_c = round(math.degrees(math.acos((self.lado_1 ** 2 +
                         self.lado_2 ** 2 - self.lado_3 ** 2) /
                         (2 * self.lado_1 * self.lado_2))), 2)
        return angulo_a, angulo_b, angulo_c
 
    def area_3_lados(self):
        '''(número, número, número) -> número

        Función que calcula el área de un triángulo en función de sus
        tres lados.

        Atributos:
            lado_1 --- Primer lado del triángulo.
            lado_2 --- Segundo lado del triángulo.
            lado_3 --- Tercer lado del triángulo.

        Ejemplos de uso:
            >>> area_3_lados(3, 4, 5)
            6
        '''
 
        semiperimetro = (self.lado_1 + self.lado_2 + self.lado_3) / 2
        pa = semiperimetro - self.lado_1
        pb = semiperimetro - self.lado_2
        pc = semiperimetro - self.lado_3
 
        return round(math.sqrt(semiperimetro * pa * pb * pc), 2)
 
 
if __name__ == '__main__':
    lado1 = float(input('Introduce el lado a: '))
    lado2 = float(input('Introduce el lado b: '))
    lado3 = float(input('Introduce el lado c: '))
    a = Triangulo(lado1, lado2, lado3)
    mayor = a.mayor()
    mediano = a.mediano()
    menor = a.menor()
    comprueba = Triangulo.comprueba_triangulo(a)
    tipo_triangulo = Triangulo.tipo(a)
    alturas = Triangulo.altura_lado(a)
    altura_a = alturas[0]
    altura_b = alturas[1]
    altura_c = alturas[2]
    angulos = (Triangulo.angulos(a))
    angulo_1 = angulos[0]
    angulo_2 = angulos[1]
    angulo_3 = angulos[2]
 
    # Presentación de resultados
    print()
    print('LADOS')
    print('=====')
    print('a = {0} u'.format(a.lado_1))
    print('b = {0} u'.format(a.lado_2))
    print('c = {0} u'.format(a.lado_3))
    print()
    print('ÁNGULOS')
    print('=======')
    print('A = {0}º'.format(angulo_1))
    print('B = {0}º'.format(angulo_2))
    print('C = {0}º'.format(angulo_3))
    print()
    print('ALTURAS')
    print('=======')
    print('h_a = {0} u'.format(altura_a))
    print('h_b = {0} u'.format(altura_b))
    print('h_c = {0} u'.format(altura_c))
    print()
    print('El triángulo es: {0}'.format(tipo_triangulo))
 
    area = Triangulo.area_3_lados(a)
    print('')
    print('El área del triángulo A es de {0} u²'.format(area))
    print('')

El resultado es:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
Introduce el lado a: 3
Introduce el lado b: 4
Introduce el lado c: 5
 
LADOS
=====
a = 3.0 u
b = 4.0 u
c = 5.0 u
 
ÁNGULOS
=======
A = 36.87º
B = 53.13º
C = 90.
 
ALTURAS
=======
h_a = 4.0 u
h_b = 3.0 u
h_c = 2.4 u
 
El triángulo es: rectángulo
 
El área del triángulo A es de 6.0 u²

En principio, la clase funciona correctamente. Pero mi problema surge cuando importo esta clase desde otro archivo y quiero utilizar una de sus funciones. Por ejemplo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#! /usr/bin/env python3
# -*- coding:utf-8 -*-
 
import triangulos
 
lado1 = float(input('Introduce el lado a: '))
lado2 = float(input('Introduce el lado b: '))
lado3 = float(input('Introduce el lado c: '))
a = triangulos.Triangulo(lado1, lado2, lado3)
mayor = a.mayor()
mediano = a.mediano()
menor = a.menor()
comprueba = triangulos.Triangulo.comprueba_triangulo(a)
tipo_triangulo = triangulos.Triangulo.tipo(a)
alturas = triangulos.Triangulo.altura_lado(a)
altura_a = alturas[0]
altura_b = alturas[1]
altura_c = alturas[2]
angulos = (triangulos.Triangulo.angulos(a))
angulo_1 = angulos[0]
angulo_2 = angulos[1]
angulo_3 = angulos[2]
 
# Presentación de resultados
print()
print('LADOS')
print('=====')
print('a = {0} u'.format(a.lado_1))
print('b = {0} u'.format(a.lado_2))
print('c = {0} u'.format(a.lado_3))
print()
print('ÁNGULOS')
print('=======')
print('A = {0}º'.format(angulo_1))
print('B = {0}º'.format(angulo_2))
print('C = {0}º'.format(angulo_3))
print()
print('ALTURAS')
print('=======')
print('h_a = {0} u'.format(altura_a))
print('h_b = {0} u'.format(altura_b))
print('h_c = {0} u'.format(altura_c))
print()
print('El triángulo es: {0}'.format(tipo_triangulo))
 
area = triangulos.Triangulo.area_3_lados(a)
print()
print('El área del triángulo A es de {0} u²'.format(area))
print()
 
# Ejemplo de uso de una función importada de triangulos.
 
print(triangulos.Triangulo.mayor(2,3,4))

Esto arroja el siguiente resultado:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
Introduce el lado a: 3
Introduce el lado b: 4
Introduce el lado c: 5
 
LADOS
=====
a = 3.0 u
b = 4.0 u
c = 5.0 u
 
ÁNGULOS
=======
A = 36.87º
B = 53.13º
C = 90.
 
ALTURAS
=======
h_a = 4.0 u
h_b = 3.0 u
h_c = 2.4 u
 
El triángulo es: rectángulo
 
El área del triángulo A es de 6.0 u²
 
Traceback (most recent call last):
  File "/home/miguel/Escritorio/matematicas/grafica.py", line 203, in <module>
    print(triangulos.Triangulo.mayor(2,3,4))
TypeError: mayor() takes 1 positional argument but 3 were given

De inglés estoy fatal, pero creo entender que el mensaje dice que el método "mayor" sólo admite un argumento y le estamos pasando tres. Y esto me plantea la duda: ¿Es que no se pueden utilizar funciones importadas de una clase? ¿O estoy escribiendo mal el código?

Yo creo que es lo último. Si alguien puede ayudarme se lo agradecería, porque mi conocimiento de python es nulo y en cuanto a la programación estoy peor. Yo creía que la ventaja de escribir funciones y clases era poder reutilizar el código.

Gracias y perdón por haber sido tan extenso.
Valora esta pregunta
Me gusta: Está pregunta es útil y esta claraNo me gusta: Está pregunta no esta clara o no es útil
0
Responder
Imágen de perfil de kip
Val: 1.120
Bronce
Ha mantenido su posición en Python (en relación al último mes)
Gráfica de Python

Duda sobre las clases en python

Publicado por kip (257 intervenciones) el 14/05/2018 19:35:51
Hola, el error, tal como dices, es de argumentos, si te fijas el metodo mayor en realidad no recibe ningún argumento (excluyendo self que se usa internamente para identificar la instancia actual desde donde se llama)

1
def mayor(self):

Intenta redefinir bien los metodos que usas, que este acorde a su doc que tu mismo definiste tambien.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

Duda sobre las clases en python

Publicado por Miguel (8 intervenciones) el 14/05/2018 19:55:44
Gracias por responder.

El caso es que había contemplado la posibilidad el tema de los argumentos, pero en la importación sigue sin funcionar.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# Este es el código de la clase Triangulo, modificado para poner los arumentos (sólo el metodo "mayor")
 
def mayor(self, lado_1, lado_2, lado_3):
        '''(número, número, número) -> número

        Método que comprueba que lado del triángulo es el mayor.

        Atributos:
            lado_1 --- Primer lado del triángulo.
            lado_2 --- Segundo lado del triángulo.
            lado_3 --- Tercer lado del triángulo.

        Ejemplos de uso:
            >>> mayor(3, 4, 5)
            5
        '''
 
        mayor = self.lado_1
        if self.lado_2 > mayor:
            mayor = self.lado_2
        if self.lado_3 > mayor:
            mayor = self.lado_3
        return mayor

Y este es el resultado de ejecutarlo desde el módulo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
Introduce el lado a: 3
Introduce el lado b: 4
Introduce el lado c: 5
 
LADOS
=====
a = 3.0 u
b = 4.0 u
c = 5.0 u
 
ÁNGULOS
=======
A = 36.87º
B = 53.13º
C = 90.
 
ALTURAS
=======
h_a = 4.0 u
h_b = 3.0 u
h_c = 2.4 u
 
El triángulo es: rectángulo
 
El área del triángulo A es de 6.0 u²

Pero al ejecutarlo desde la importación:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
import triangulos
 
lado1 = float(input('Introduce el lado a: '))
lado2 = float(input('Introduce el lado b: '))
lado3 = float(input('Introduce el lado c: '))
a = triangulos.Triangulo(lado1, lado2, lado3)
mayor = a.mayor(lado1, lado2, lado3)
mediano = a.mediano()
menor = a.menor()
comprueba = triangulos.Triangulo.comprueba_triangulo(a)
tipo_triangulo = triangulos.Triangulo.tipo(a)
alturas = triangulos.Triangulo.altura_lado(a)
altura_a = alturas[0]
altura_b = alturas[1]
altura_c = alturas[2]
angulos = (triangulos.Triangulo.angulos(a))
angulo_1 = angulos[0]
angulo_2 = angulos[1]
angulo_3 = angulos[2]
 
# Presentación de resultados
print()
print('LADOS')
print('=====')
print('a = {0} u'.format(a.lado_1))
print('b = {0} u'.format(a.lado_2))
print('c = {0} u'.format(a.lado_3))
print('')
print('ÁNGULOS')
print('=======')
print('A = {0}º'.format(angulo_1))
print('B = {0}º'.format(angulo_2))
print('C = {0}º'.format(angulo_3))
print('')
print('ALTURAS')
print('=======')
print('h_a = {0} u'.format(altura_a))
print('h_b = {0} u'.format(altura_b))
print('h_c = {0} u'.format(altura_c))
print('')
print('El triángulo es: {0}'.format(tipo_triangulo))
 
area = triangulos.Triangulo.area_3_lados(a)
print('')
print('El área del triángulo A es de {0} u²'.format(area))
print('')
 
# Ejemlo de uso de una función importada de triangulos.
 
print(triangulos.Triangulo.mayor(2,3,4))

El resultado es:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
Introduce el lado a: 2
Introduce el lado b: 3
Introduce el lado c: 4
 
LADOS
=====
a = 2.0 u
b = 3.0 u
c = 4.0 u
 
ÁNGULOS
=======
A = 28.96º
B = 46.57º
C = 104.48º
 
ALTURAS
=======
h_a = 2.9 u
h_b = 1.94 u
h_c = 1.45 u
 
El triángulo es: obtusángulo
 
El área del triángulo A es de 2.9 u²
 
Traceback (most recent call last):
  File "/home/miguel/Escritorio/matematicas/grafica.py", line 203, in <module>
    print(triangulos.Triangulo.mayor(2,3,4))
TypeError: mayor() missing 1 required positional argument: 'lado_3'

Entiendo que me dice que no he introducido el argumento "lado_3". Esto es lo que me desconcierta, porque yo creía que el argumento "self" sólo contaba internamente para hacerse referencia a sí mismo.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

Duda sobre las clases en python

Publicado por Miguel Angel (1 intervención) el 11/07/2018 19:50:31
Hola Miguel.

¿Conseguiste averiguar el error ese a qué se debe? Estoy ahora mismo exactamente igual que tú.

Gracias!!
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

Duda sobre las clases en python

Publicado por Migiel (8 intervenciones) el 24/07/2018 03:18:10
Buenos dias, Miguel Angel.

Perdon por tardar en responder. Lo cierto es que no he conseguido resolverlo. Sera que cuando haces una clase, sus metodos solo pueden utilizatse como parte de esa clase.

Saludos.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar
Imágen de perfil de jcanizalesc
Val: 16
Ha disminuido su posición en 8 puestos en Python (en relación al último mes)
Gráfica de Python

Duda sobre las clases en python

Publicado por jcanizalesc (2 intervenciones) el 26/07/2018 04:27:00
Hola un saludo.

Estoy aprendiendo el lenguaje python y en este momento estoy en el punto de las clases
así que tomare tu código y le meteré mano para tratar de entender este concepto de POO.

si resuelvo el problema lo comento ok

Saludos.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar
Imágen de perfil de jcanizalesc
Val: 16
Ha disminuido su posición en 8 puestos en Python (en relación al último mes)
Gráfica de Python

Duda sobre las clases en python

Publicado por jcanizalesc (2 intervenciones) el 26/07/2018 05:35:07
Lo primero que veo que el método "mayor" no recibe argumentos
así que hice esta pequeña modificación y funciono a la primera.

print(triangulos.Triangulo(2, 3, 4).mayor())

PD. no se si sera la forma correcta de la llamada del método
pero al menos funciono.

Saludos.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar