2016-12-02 1 views
0

J'écris une fonction de codage personnalisée à utiliser avec msgpack-python. Je souhaite convertir n'importe quel objet numpy.float en flottant avant de laisser msgpack-python le sérialiser. Ma fonction de codage ressemble à ceci:Duck en tapant des types float numpy

def encode_custom(obj):   
    if issubclass(obj.__class__,np.float): 
     obj = float(obj) 
    return obj 

qui fonctionne très bien. Cependant, la réponse la mieux votée au How do I check (at runtime) if one class is a subclass of another? suggère que c'est une mauvaise idée. Je suppose que c'est parce que cette méthode n'utilise pas de dactylographie.

Existe-t-il un moyen de dactylographier la fonction de codage?

EDIT: Notez que je veux seulement que les objets de type float soient convertis en float. Les objets qui sont mieux représentés comme un autre type (par exemple ints) devraient utiliser cet autre type, même s'ils peuvent être float() 'd dans un objet flottant.

+2

'essayer: flotteur de retour (obj) sauf ValueError : return obj' – SethMMorton

+0

@SethMMorton Cela convertit aussi les entiers en float. –

+1

C'est une mauvaise idée dans certains cas. Vous avez spécifiquement dit que vous voulez convertir des flotteurs numpy, donc cela semble bien. Cependant, je suggère simplement d'utiliser 'isinstance (obj, np.float)'. –

Répondre

2

boîtier spécial du type ici est tout à fait raisonnable - car il semble que vous nourrissez dans une API qui ne fonctionne pas avec le canard-frappe de toute façon.

Mais comme mentionné ailleurs, np.float is float, donc cela ne va pas fonctionner. Vous voulez probablement soit isinstance(val, np.floating), soit isinstance(val, np.inexact).

Pour référence ultérieure, si vous voulez savoir ce que l'ensemble de la hiérarchie des classes (à l'exception abc s) est, vous pouvez l'obtenir avec la propriété .__mro__:

>>> np.float32.__mro__ 
(<class 'numpy.float32'>, <class 'numpy.floating'>, <class 'numpy.inexact'>, <class 'numpy.number'>, <class 'numpy.generic'>, <class 'object'>) 
+0

La pointe __mro__ a été très appréciée. – Charlie

+0

Ou 'np.float32.mro()', c'est-à-dire via une méthode, où MRO signifie _method resolution order_ –

0

Vous pouvez appeler l'un des routines numpy qui convertissent numpy scalaires Python scalaires:

try: 
    return obj.item() 
except AttributeError: 
    return obj 

ou

try: 
    return obj.tolist() # yes, tolist. It won't return a list here. 
except AttributeError: 
    return obj 

Notez qu'il pourrait être préférable de simplement utiliser isinstance(obj, numpy.float64) ou isinstance(obj, (numpy.float32, numpy.float64)). La dactylographie a du sens pour les choses comme les itérations, où vous essayez de les traiter comme des itérations, et si cela fonctionne, vous savez qu'elles sont itérables. Ici? Vous essayez de traiter votre objet comme un scalaire numpy, et si cela fonctionne, vous savez ... que l'objet a une méthode item, ou une méthode tolist. Ce n'est pas vraiment l'information que vous êtes intéressé.

Si vous voulez vérifier si un objet a un type réel, spécifique, plutôt que de vérifier quelles opérations il fournit, isinstance est généralement le chemin à parcourir.

0

La réponse numéro 1 à n'importe quelle question python est "ça dépend". Avec le Duck-Typing, vous utilisez simplement l'objet en supposant que c'est correct et attrapez des exceptions quand tout va mal. Dans votre cas, ce serait:

def encode_custom(obj): 
    """Strict type checking: change to float, but raise ValueError 
    on fail and let upper level deal with it.""" 
    return float(obj) 

def encode_custom(obj): 
    """Loose type checking: change to float or return unchanged""" 
    try: 
     return float(obj) 
    except ValueError: 
     return obj 

Cela fonctionnerait avec les différents flotteurs et avec tout ce qui peut être converti en un flotteur. des choses comme np.int16, np.bool_ et str (s'il s'agit de représenter un int ou un flottant). Maintenant à la "ça dépend". C'est très bien si vous voulez que toutes ces choses soient secrètes ou moche si votre programme définit ces choses non-flottantes comme des ordures et que vous voulez faire une erreur.

Dans ce cas, au lieu de vérifier la sous-classe, vérifiez l'instance afin de pouvoir gérer tout héritage multiple bizarre ou méta-programmation qui se passe.

def encode_custom(obj):   
    if isinstance(obj,np.float): 
     obj = float(obj) 
    return obj 
+2

Notez que 'np.float' est juste un autre nom pour le' float' intégré de Python. Plus important encore, notez que 'isinstance (np.float32 (1.0), float)' retourne 'False'. –

+1

@WarrenWeckesser - Intéressant. J'ai vérifié 'np.float64' et cela a fonctionné. 'issubclass' pour' np.float32' ne fonctionne pas non plus. Hmmm .... – tdelaney