type library define argument python strong-typing weak-typing

library - typing io python



¿Python está fuertemente tipado? (10)

Me he encontrado con enlaces que dicen que Python es un lenguaje fuertemente tipado.

Sin embargo, pensé que en los lenguajes fuertemente tipados no podrías hacer esto:

bob = 1 bob = "bob"

Pensé que un lenguaje fuertemente tipado no aceptaba cambios de tipo en el tiempo de ejecución. Tal vez tengo una definición incorrecta (o demasiado simplista) de tipos fuertes / débiles.

Entonces, ¿Python es un lenguaje fuertemente o débilmente tipado?


TLDR;

El tipado de Python es dinámico, por lo que puede cambiar una variable int por una cadena

x = ''somestring'' x = 50

La tipificación de Python es Strong, por lo que no puede combinar tipos:

''x'' + 3 --> TypeError: cannot concatenate ''str'' and ''int'' objects

En Javascript de tipo débil, esto sucede ...

''x''+3 = ''x3''

En cuanto a la inferencia de tipo

Java te obliga a declarar explícitamente tus tipos de objetos

int x = 50

Kotlin utiliza la inferencia para darse cuenta de que es una int

x = 50

Pero como ambos lenguajes usan tipos estáticos, x no se puede cambiar desde un int . Ninguno de los dos idiomas permitiría un cambio dinámico como

x = 50 x = ''now a string''


Creo que este simple ejemplo debe explicar las diferencias entre la tipificación fuerte y dinámica:

>>> tup = (''1'', 1, .1) >>> for item in tup: ... type(item) ... <type ''str''> <type ''int''> <type ''float''> >>>

Java:

public static void main(String[] args) { int i = 1; i = "1"; //will be error i = ''0.1''; // will be error }


De acuerdo con este wiki, el artículo de Python Python está tipado de manera dinámica y fuerte (también proporciona una buena explicación).

Tal vez esté pensando en idiomas con tipado estático donde los tipos no pueden cambiar durante la ejecución del programa y la verificación de tipos ocurre durante el tiempo de compilación para detectar posibles errores.

Esta pregunta de SO podría ser de interés: los lenguajes de tipo dinámico frente a los de tipo estático y este artículo de Wikipedia sobre Type Systems proporciona más información


El término "tipado fuerte" no tiene una definición definida.

Por lo tanto, el uso del término depende de con quién está hablando.

No considero ningún lenguaje, en el que el tipo de una variable no se declare explícitamente, o se tipee estáticamente para que se escriba fuertemente.

Escribir fuerte no solo impide la conversión (por ejemplo, la conversión "automática" de un entero a una cadena). Impide la asignación (es decir, cambiar el tipo de una variable).

Si el siguiente código compila (interpreta), el lenguaje no es de tipo fuerte:

Foo = 1 Foo = "1"

En un lenguaje fuertemente tipado, un programador puede "contar con" un tipo.

Por ejemplo, si un programador ve la declaración,

UINT64 kZarkCount;

y él o ella sabe que 20 líneas después, kZarkCount sigue siendo un UINT64 (siempre que ocurra en el mismo bloque) - sin tener que examinar el código intermedio.


Está confundiendo ''fuertemente tipeado'' con ''tipeado dinámicamente'' .

No puedo cambiar el tipo de 1 agregando la cadena ''12'' , pero puedo elegir qué tipos almaceno en una variable y cambiar eso durante el tiempo de ejecución del programa.

Lo opuesto a la tipificación dinámica es el tipado estático; la declaración de tipos de variables no cambia durante la vida útil de un programa. Lo opuesto a la tipificación fuerte es la tipificación débil; el tipo de valores puede cambiar durante la vida útil de un programa.


Hay algunos asuntos importantes que creo que todas las respuestas existentes se han perdido.

Escribir débil significa permitir el acceso a la representación subyacente. En C, puedo crear un puntero a los caracteres, luego decirle al compilador que quiero usarlo como un puntero a los enteros:

char sz[] = "abcdefg"; int *i = (int *)sz;

En una plataforma little-endian con enteros de 32 bits, esto i convierte en una matriz de números 0x64636261 y 0x00676665 . De hecho, incluso puede lanzar punteros a números enteros (del tamaño apropiado):

intptr_t i = (intptr_t)&sz;

Y, por supuesto, esto significa que puedo sobrescribir la memoria en cualquier lugar del sistema. *

char *spam = (char *)0x12345678 spam[0] = 0;

* Por supuesto, los sistemas operativos modernos usan memoria virtual y protección de páginas, así que solo puedo sobrescribir la memoria de mi propio proceso, pero C no ofrece protección, como cualquiera que haya codificado, digamos, Classic Mac OS o Win16.

El Lisp tradicional permitía tipos similares de hackers; en algunas plataformas, las flotantes de doble palabra y las contras eran del mismo tipo, y se podía pasar una a una función esperando la otra y "funcionaría".

La mayoría de los idiomas de hoy en día no son tan débiles como C y Lisp, pero muchos de ellos todavía tienen algún tipo de filtración. Por ejemplo, cualquier lenguaje OO que tenga un "downcast" sin marcar *, es una pérdida de tipo: básicamente le está diciendo al compilador "Sé que no le di suficiente información para saber que esto es seguro, pero estoy bastante seguro es decir, "cuando el objetivo de un sistema de tipos es que el compilador siempre tenga suficiente información para saber qué es seguro.

* Un downcast marcado no hace que el sistema de tipos de idioma sea más débil solo porque mueve el control al tiempo de ejecución. Si lo hiciera, entonces el polimorfismo del subtipo (también conocido como llamadas a funciones virtuales o completamente dinámicas) sería la misma violación del sistema de tipo, y no creo que nadie quiera decir eso.

Muy pocos lenguajes "scripting" son débiles en este sentido. Incluso en Perl o Tcl, no puede tomar una cadena e interpretar sus bytes como un entero. * Pero vale la pena señalar que en CPython (y de manera similar para muchos otros intérpretes para muchos idiomas), si es realmente persistente, puede usar ctypes para cargar libpython , convertir el id un objeto en un POINTER(Py_Object) y forzar al sistema de tipo a fugarse. Si esto hace que el sistema de tipos sea débil o no depende de sus casos de uso: si está tratando de implementar un entorno limitado de ejecución restringida en lenguaje para garantizar la seguridad, debe lidiar con este tipo de escapes ...

* Puede usar una función como struct.unpack para leer los bytes y crear un nuevo int de "cómo C representaría estos bytes", pero obviamente no tiene goteras; incluso Haskell lo permite.

Mientras tanto, la conversión implícita es realmente una cosa diferente de un sistema de tipo débil o con fugas.

Todos los lenguajes, incluso Haskell, tienen funciones para, por ejemplo, convertir un entero en una cuerda o un flotador. Sin embargo, algunos idiomas realizarán automáticamente algunas de esas conversiones; por ejemplo, en C, si llama a una función que quiere un float y la pasa en int , se convierte para usted. Esto definitivamente puede conducir a errores con, por ejemplo, desbordamientos inesperados, pero no son los mismos tipos de errores que se obtienen de un sistema de tipo débil. Y C no está siendo realmente más débil aquí; puedes agregar un int y un float en Haskell, o incluso concatenar un float en una cadena, solo tienes que hacerlo de manera más explícita.

Y con lenguajes dinámicos, esto es bastante turbio. No existe tal cosa como "una función que quiere flotar" en Python o Perl. Pero hay funciones sobrecargadas que hacen cosas diferentes con diferentes tipos, y hay un fuerte sentido intuitivo de que, por ejemplo, agregar una cadena a otra cosa es "una función que quiere una cadena". En ese sentido, Perl, Tcl y JavaScript parecen hacer muchas conversiones implícitas ( "a" + 1 le da "a1" ), mientras que Python lo hace mucho menos ( "a" + 1 plantea una excepción, pero 1.0 + 1 te da 2.0 *). Es difícil poner ese sentido en términos formales: ¿por qué no debería haber un + que toma una cadena y un int, cuando obviamente hay otras funciones, como la indexación, que hacen?

* En realidad, en Python moderno, eso se puede explicar en términos de subtipificación OO, ya que isinstance(2, numbers.Real) es verdadero. No creo que haya ningún sentido en el que 2 sea ​​una instancia del tipo de cadena en Perl o JavaScript ... aunque en Tcl, en realidad lo es, ya que todo es una instancia de cadena.

Finalmente, hay otra definición completamente ortogonal de tipeo "fuerte" contra "débil", donde "fuerte" significa poderoso / flexible / expresivo.

Por ejemplo, Haskell le permite definir un tipo que es un número, una cadena, una lista de este tipo o un mapa de cadenas para este tipo, que es una manera perfecta de representar cualquier cosa que pueda decodificarse desde JSON. No hay forma de definir dicho tipo en Java. Pero al menos Java tiene tipos paramétricos (genéricos), por lo que puede escribir una función que tome una Lista de T y sepa que los elementos son de tipo T; otros lenguajes, como los primeros Java, lo forzaron a usar una Lista de objetos y downcast. Pero al menos Java te permite crear nuevos tipos con sus propios métodos; C solo te permite crear estructuras. Y BCPL ni siquiera tenía eso. Y así sucesivamente hasta el ensamblaje, donde los únicos tipos son diferentes longitudes de bits.

Entonces, en ese sentido, el sistema de tipos de Haskell es más fuerte que el de Java moderno, que es más fuerte que el anterior de Java, que es más fuerte que el de C, que es más fuerte que el de BCPL.

Entonces, ¿dónde encaja Python en ese espectro? Eso es un poco complicado. En muchos casos, el tipado de pato le permite simular todo lo que puede hacer en Haskell, e incluso algunas cosas que no puede hacer; seguro, los errores se capturan en tiempo de ejecución en lugar de compilar, pero aún están atrapados. Sin embargo, hay casos en los que la tipificación de pato no es suficiente. Por ejemplo, en Haskell, puedes decir que una lista vacía de entradas es una lista de entradas, por lo que puedes decidir que reducir + sobre esa lista debería devolver 0 *; en Python, una lista vacía es una lista vacía; no hay información de tipo que lo ayude a decidir qué reducción + debería hacer.

* De hecho, Haskell no te deja hacer esto; si llama a la función de reducción que no toma un valor de inicio en una lista vacía, se obtiene un error. Pero su sistema de tipos es lo suficientemente potente como para hacer que esto funcione, y Python no.


Python tiene un tipado fuerte y dinámico.

  • Escribir fuerte significa que el tipo de valor no cambia repentinamente. Una cadena que contiene solo dígitos no se convierte mágicamente en un número, como puede suceder en Perl. Cada cambio de tipo requiere una conversión explícita.
  • El tipado dinámico significa que los objetos en tiempo de ejecución (valores) tienen un tipo, a diferencia del tipado estático donde las variables tienen un tipo.

En cuanto a tu ejemplo

bob = 1 bob = "bob"

Esto funciona porque la variable no tiene un tipo; puede nombrar cualquier objeto. Después de bob=1 , encontrará que el type(bob) devuelve int , pero después de bob="bob" , devuelve str . (Tenga en cuenta que el type es una función regular, por lo que evalúa su argumento, luego devuelve el tipo del valor).

Contraste esto con los dialectos más antiguos de C, que estaban débilmente tipados estáticamente, de modo que los punteros y los enteros eran bastante intercambiables. (El ISO C moderno requiere conversiones en muchos casos, pero mi compilador todavía es indulgente con esto por defecto).

Debo agregar que la tipificación fuerte vs. débil es más un continuo que una opción booleana. C ++ tiene un tipado más fuerte que C (se requieren más conversiones), pero el sistema de tipos se puede subvertir utilizando moldes de puntero.

La fortaleza del sistema de tipos en un lenguaje dinámico como Python está realmente determinado por cómo responden los primitivos y las funciones de la biblioteca a diferentes tipos. Por ejemplo, + está sobrecargado para que funcione en dos números o dos cadenas, pero no en una cadena y un número. Esta es una opción de diseño hecha cuando + se implementó, pero no es realmente una necesidad de seguimiento de la semántica del lenguaje. De hecho, cuando sobrecarga + en un tipo personalizado, puede convertirlo implícitamente en un número:

def to_number(x): """Try to convert x to a number.""" if x is None: return 0 # more special cases here else: return float(x) # works for numbers and strings class Foo(object): def __add__(self, other): other = to_number(other) # now do the addition

(El único lenguaje que sé que está completamente tipado, también conocido como estrictamente mecanografiado, es Haskell, donde los tipos son completamente disjuntos y solo es posible una sobrecarga controlada a través de clases de tipos).


Una variable de Python almacena una referencia sin tipo al objeto de destino que representa el valor.

Cualquier operación de asignación significa asignar la referencia sin tipo al objeto asignado, es decir, el objeto se comparte a través de las referencias originales y nuevas (contadas).

El tipo de valor está vinculado al objeto de destino, no al valor de referencia. La verificación de tipo (fuerte) se realiza cuando se realiza una operación con el valor (tiempo de ejecución).

En otras palabras, las variables (técnicamente) no tienen ningún tipo; no tiene sentido pensar en términos de un tipo de variable si se quiere ser exacto. Pero las referencias se desreferencian automáticamente y realmente pensamos en términos del tipo de objeto objetivo.


Ya ha sido respondida varias veces, pero Python es un lenguaje fuertemente tipado:

>>> x = 3 >>> y = ''4'' >>> print(x+y) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: unsupported operand type(s) for +: ''int'' and ''str''

Lo siguiente en JavaScript:

var x = 3 var y = ''4'' alert(x + y) //Produces "34"

Esa es la diferencia entre tipeo débil y tipeo fuerte. Los tipos débiles automáticamente intentan convertir de un tipo a otro, dependiendo del contexto (por ejemplo, Perl). Los tipos fuertes nunca se convierten implícitamente.

Su confusión radica en un malentendido sobre cómo Python vincula los valores a los nombres (comúnmente denominados variables).

En Python, los nombres no tienen tipos, por lo que puede hacer cosas como:

bob = 1 bob = "bob" bob = "An Ex-Parrot!"

Y los nombres pueden estar vinculados a cualquier cosa:

>>> def spam(): ... print("Spam, spam, spam, spam") ... >>> spam_on_eggs = spam >>> spam_on_eggs() Spam, spam, spam, spam

Para lectura adicional:

https://en.wikipedia.org/wiki/Dynamic_dispatch

y el ligeramente relacionado pero más avanzado:

http://effbot.org/zone/call-by-object.htm


class testme(object): '''''' A test object '''''' def __init__(self): self.y = 0 def f(aTestMe1, aTestMe2): return aTestMe1.y + aTestMe2.y c = testme #get a variable to the class c.x = 10 #add an attribute x inital value 10 c.y = 4 #change the default attribute value of y to 4 t = testme() # declare t to be an instance object of testme r = testme() # declare r to be an instance object of testme t.y = 6 # set t.y to a number r.y = 7 # set r.y to a number print(f(r,t)) # call function designed to operate on testme objects r.y = "I am r.y" # redefine r.y to be a string print(f(r,t)) #POW!!!! not good....

Lo anterior crearía una pesadilla de código inmanejable en un sistema grande durante un largo período de tiempo. Llámalo como quieras, pero la capacidad de "cambiar dinámicamente" un tipo de variable es solo una mala idea ...