类构造函数要求浮点数或无。如何解释浮点('nan')值?

2024-09-29 21:48:41 发布

您现在位置:Python中文网/ 问答频道 /正文

我以这样的方式编写了一个类,它需要一个floatNone。然而,事实证明,也存在float('nan')值的可能性。我正在寻找一个干净的方法来解决它

from typing import Optional
from dataclasses import dataclass

@dataclass
class PricingLimits:
    min_price   : Optional[float] = None
    min_percent : Optional[float] = None
    max_percent : Optional[float] = None
    min_delta   : Optional[float] = None

到目前为止,我看到两种可能性:

  1. 忘掉None,只期待float。使用float('nan')而不是None
  2. 以某种方式定义一个数字浮动的数据类型:not nan(not inf)。我不知道该怎么做,但如果我做了:
@dataclass
class PricingLimits:
    min_price   : Optional[NumberFloat] = None
    min_percent : Optional[NumberFloat] = None
    max_percent : Optional[NumberFloat] = None
    min_delta   : Optional[NumberFloat] = None
# And use a validator like Pydantic

好的,我也可以这样做:

from pydantic import root_validator
from pydantic.dataclasses import dataclass
import numpy as np

@dataclass
class PricingLimits:
    min_price   : Optional[float] = None
    min_percent : Optional[float] = None
    max_percent : Optional[float] = None
    min_delta   : Optional[float] = None

    @root_validator
    def nan_to_none(cls, values):
        for k, v in values.items():
            if np.isnan(v):
                values[k] = None
        return values

这样,在对象实例化时,所有nan值都将自动转换为None

你对此有什么看法


Tags: fromimportnonenanfloatminpriceoptional
1条回答
网友
1楼 · 发布于 2024-09-29 21:48:41

如果您想使用numpy或pandas进行数学运算,最好将NaN值保留为np.nan,因此我会做相反的事情,我会将None替换为np.nan

使用np.nan(超过None)的主要原因是它可以与numpyfloat64 dtype一起存储,而不是使用效率较低的object dtypenp.nan允许向量化操作,而None根据定义,禁用numpy中的所有效率

另一个很好的原因是NaN被用作熊猫中缺失数据的占位符:pandas docs

import numpy as np

class PricingLimits:
    
    
    def __init__(self,
                    min_price: float = np.nan,
                    min_percent: float = np.nan,
                    max_percent: float = np.nan,
                    min_delta: float = np.nan):
        

        if not min_price:
            self.min_price = np.nan
        else:
            self.min_price = min_price
            
        if not min_percent:
            self.min_percent = np.nan
        else:
            self.min_percent = min_percent
            
        if not max_percent:
            self.max_percent = np.nan
        else:
            self.max_percent = max_percent
            
        if not min_delta:
            self.min_delta = np.nan
        else:
            self.min_delta = min_delta

如果您的目标是拥有一个值或None(这就是有人会使用Optional[x]的原因),并且值仅在实例化时设置,那么将np.nan转换为None是正确的方法:

import numpy as np
from typing import Optional

class PricingLimits:
    
    
    def __init__(self,
                    min_price: Optional[float] = None,
                    min_percent: Optional[float] = None,
                    max_percent: Optional[float] = None,
                    min_delta: Optional[float] = None):
        

        if not min_price or np.isnan(min_price):
            self.min_price = None
        else:
            self.min_price = min_price
            
        if not min_percent or np.isnan(min_percent):
            self.min_percent = None
        else:
            self.min_percent = min_percent
            
        if not max_percent or np.isnan(max_percent):
            self.max_percent = None
        else:
            self.max_percent = max_percent
            
        if not min_delta or np.isnan(min_delta):
            self.min_delta = None
        else:
            self.min_delta = min_delta
            

如果希望在实例化后自由更改值,可以使用属性,但这会影响性能:

import numpy as np
from typing import Optional

class PricingLimits:
    
    @property
    def min_price(self):
        return self._min_price
    
    @min_price.setter
    def min_price(self, value):
        if not value or np.isnan(value):
            self._min_price = None
        else:
            self._min_price = value
            
    @property
    def min_percent(self):
        return self._min_percent
    
    @min_percent.setter
    def min_percent(self, value):
        if not value or np.isnan(value):
            self._min_percent = None
        else:
            self._min_percent = value
    
    @property
    def max_percent(self):
        return self._max_percent
    
    @max_percent.setter
    def max_percent(self, value):
        if not value or np.isnan(value):
            self._max_percent = None
        else:
            self._max_percent = value
    
    @property
    def min_delta(self):
        return self._min_delta
    
    @min_delta.setter
    def min_delta(self, value):
        if not value or np.isnan(value):
            self._min_delta = None
        else:
            self._min_delta = value
    
    def __init__(self,
                    min_price: Optional[float] = None,
                    min_percent: Optional[float] = None,
                    max_percent: Optional[float] = None,
                    min_delta: Optional[float] = None):
        
            self.min_price = min_price
            self.min_percent = min_percent
            self.max_percent = max_percent
            self.min_delta = min_delta

相关问题 更多 >

    热门问题