str - tipos de datos en python pdf
Determinar el tipo de un objeto? (9)
Determine el tipo de un objeto Python
Determinar el tipo de un objeto con type
>>> obj = object()
>>> type(obj)
<class ''object''>
Aunque funciona, evite los atributos de subrayado doble como __class__
- no son semánticamente públicos y, aunque quizás no en este caso, las funciones integradas generalmente tienen un mejor comportamiento.
>>> obj.__class__ # avoid this!
<class ''object''>
verificación de tipos
¿Hay una forma sencilla de determinar si una variable es una lista, un diccionario o algo más? Estoy recuperando un objeto que puede ser de cualquier tipo y necesito poder notar la diferencia.
Bueno, esa es una pregunta diferente, no uses tipo - usa isinstance
:
def foo(obj):
"""given a string with items separated by spaces,
or a list or tuple,
do something sensible
"""
if isinstance(obj, str):
obj = str.split()
return _foo_handles_only_lists_or_tuples(obj)
Esto cubre el caso en el que su usuario podría estar haciendo algo inteligente o sensato mediante la subclasificación de str
. De acuerdo con el principio de Sustitución de Liskov, usted quiere poder usar instancias de subclases sin romper su código, y la isinstance
admite.
Utilizar abstracciones
Aún mejor, puede buscar una clase base abstracta abstracta de collections
o numbers
:
from collections import Iterable
from numbers import Number
def bar(obj):
"""does something sensible with an iterable of numbers,
or just one number
"""
if isinstance(obj, Number): # make it a 1-tuple
obj = (obj,)
if not isinstance(obj, Iterable):
raise TypeError(''obj must be either a number or iterable of numbers'')
return _bar_sensible_with_iterable(obj)
O simplemente no hacer explícitamente la comprobación de tipo
O, quizás lo mejor de todo, utilice la tipificación de pato y no compruebe explícitamente su código. La tipificación del pato admite la sustitución de Liskov con más elegancia y menos verbosidad.
def baz(obj):
"""given an obj, a dict (or anything with an .items method)
do something sensible with each key-value pair
"""
for key, value in obj.items():
_baz_something_sensible(key, value)
Conclusión
- Utilice el
type
para obtener realmente la clase de una instancia. - Use
isinstance
para verificar explícitamente las subclases reales o las abstracciones registradas. - Y simplemente evite la comprobación de tipos donde tenga sentido.
¿Hay una forma sencilla de determinar si una variable es una lista, un diccionario o algo más? Estoy recuperando un objeto que puede ser de cualquier tipo y necesito poder notar la diferencia.
Además de las respuestas anteriores, vale la pena mencionar la existencia de collections.abc
que contiene varias clases base abstractas (ABC) que complementan la tipificación de pato.
Por ejemplo, en lugar de verificar explícitamente si algo es una lista con:
isinstance(my_obj, list)
podría, si solo está interesado en ver si el objeto que tiene permite obtener artículos, utilice collections.abc.Sequence
:
from collections.abc import Sequence
isinstance(my_obj, Sequence)
Si está estrictamente interesado en los objetos que permiten obtener, configurar y eliminar elementos (es decir, secuencias mutables ), debería optar por collections.abc.MutableSequence
.
Muchos otros ABC se definen allí, Mapping
de objetos que se pueden usar como mapas, Iterable
, Callable
, etc. Se puede ver una lista completa de todo esto en la documentación de collections.abc
.
En instancias de objeto también tiene el:
__class__
atributo. Aquí hay una muestra tomada de la consola Python 3.3.
>>> str = "str"
>>> str.__class__
<class ''str''>
>>> i = 2
>>> i.__class__
<class ''int''>
>>> class Test():
... pass
...
>>> a = Test()
>>> a.__class__
<class ''__main__.Test''>
Tenga en cuenta que en Python 3.xy clases New-Style (opcionalmente disponibles desde Python 2.6), la clase y el tipo se han fusionado y esto puede llevar a resultados inesperados. Principalmente por esta razón, mi forma favorita de probar tipos / clases es a la isinstance incorporada de isinstance .
Para obtener el tipo de un objeto, puede usar la función incorporada type()
. Pasar un objeto como único parámetro devolverá el tipo de objeto de ese objeto:
>>> type([]) is list
True
>>> type({}) is dict
True
>>> type('''') is str
True
>>> type(0) is int
True
>>> type({})
<type ''dict''>
>>> type([])
<type ''list''>
Por supuesto, esto también funciona para tipos personalizados:
>>> class Test1 (object):
pass
>>> class Test2 (Test1):
pass
>>> a = Test1()
>>> b = Test2()
>>> type(a) is Test1
True
>>> type(b) is Test2
True
Tenga en cuenta que type()
solo devolverá el tipo inmediato del objeto, pero no podrá informarle sobre la herencia de tipo.
>>> type(b) is Test1
False
Para cubrir eso, debes usar la función isinstance
. Por supuesto, esto también funciona para los tipos incorporados:
>>> isinstance(b, Test1)
True
>>> isinstance(b, Test2)
True
>>> isinstance(a, Test1)
True
>>> isinstance(a, Test2)
False
>>> isinstance([], list)
True
>>> isinstance({}, dict)
True
isinstance()
suele ser la forma preferida de asegurar el tipo de un objeto porque también aceptará los tipos derivados. Entonces, a menos que realmente necesite el tipo de objeto (por cualquier razón), se isinstance()
usar isinstance()
sobre type()
.
El segundo parámetro de isinstance()
también acepta una tupla de tipos, por lo que es posible verificar varios tipos a la vez. isinstance
luego devolverá true, si el objeto es de cualquiera de esos tipos:
>>> isinstance([], (tuple, list, set))
True
Podría ser más Pythonic usar un try
... except
bloque. De esa manera, si tienes una clase que graba como una lista, o quacks como un dict, se comportará correctamente independientemente de cuál sea su tipo realmente .
Para aclarar, el método preferido para "decir la diferencia" entre los tipos de variables es con algo que se llama tipificación de pato : siempre que los métodos (y los tipos de retorno) a los que responde una variable sean lo que espera su subrutina, trátelo como lo espera. ser. Por ejemplo, si tiene una clase que sobrecarga a los operadores de corchetes con getattr
y setattr
, pero usa algún esquema interno divertido, sería apropiado que se comporte como un diccionario si eso es lo que está tratando de emular.
El otro problema con el type(A) is type(B)
chequeo de type(A) is type(B)
es que si A
es una subclase de B
, se evalúa como false
cuando, programáticamente, desearía que fuera true
. Si un objeto es una subclase de una lista, debería funcionar como una lista: la verificación del tipo como se presenta en la otra respuesta lo evitará. ( isinstance
embargo, esta isinstance
funcionará).
Puedes hacerlo usando type()
:
>>> a = []
>>> type(a)
<type ''list''>
>>> f = ()
>>> type(f)
<type ''tuple''>
Puedes usar type()
o isinstance()
.
>>> type([]) is list
True
Tenga en cuenta que puede modificar la list
o cualquier otro tipo asignando una variable en el alcance actual del mismo nombre.
>>> the_d = {}
>>> t = lambda x: "aight" if type(x) is dict else "NOPE"
>>> t(the_d) ''aight''
>>> dict = "dude."
>>> t(the_d) ''NOPE''
Arriba vemos que el dict
se reasigna a una cadena, por lo tanto, la prueba:
type({}) is dict
... falla
Para evitar esto y usar type()
más cuidado:
>>> import __builtin__
>>> the_d = {}
>>> type({}) is dict
True
>>> dict =""
>>> type({}) is dict
False
>>> type({}) is __builtin__.dict
True
Si bien las preguntas son bastante antiguas, me topé con esto al mismo tiempo que descubrí una manera adecuada, y creo que todavía necesita aclaración, al menos para Python 2.x (no verifiqué Python 3, pero dado que el problema surge con las clases clásicas que se han ido en dicha versión, probablemente no importa).
Aquí estoy tratando de responder a la pregunta del título: ¿cómo puedo determinar el tipo de objeto arbitrario ? Otras sugerencias sobre el uso o no uso de la instancia están bien en muchos comentarios y respuestas, pero no estoy abordando esas preocupaciones.
El problema principal con el enfoque de type()
es que no funciona correctamente con instancias de estilo antiguo :
class One:
pass
class Two:
pass
o = One()
t = Two()
o_type = type(o)
t_type = type(t)
print "Are o and t instances of the same class?", o_type is t_type
Ejecutar este fragmento generaría:
Are o and t instances of the same class? True
Lo cual, sostengo, no es lo que la mayoría de la gente esperaría.
El enfoque de __class__
es el más cercano a la corrección, pero no funcionará en un caso crucial: cuando el objeto pasado es una clase de estilo antiguo (¡no es una instancia!), Ya que esos objetos carecen de dicho atributo.
Este es el fragmento de código más pequeño que se me ocurre que satisface dicha pregunta legítima de manera consistente:
#!/usr/bin/env python
from types import ClassType
#we adopt the null object pattern in the (unlikely) case
#that __class__ is None for some strange reason
_NO_CLASS=object()
def get_object_type(obj):
obj_type = getattr(obj, "__class__", _NO_CLASS)
if obj_type is not _NO_CLASS:
return obj_type
# AFAIK the only situation where this happens is an old-style class
obj_type = type(obj)
if obj_type is not ClassType:
raise ValueError("Could not determine object ''{}'' type.".format(obj_type))
return obj_type
ten cuidado al usar isinstance
isinstance(True, bool)
True
>>> isinstance(True, int)
True
pero escribe
type(True) == bool
True
>>> type(True) == int
False