类是否应该在初始化时转换参数类型?如果是,怎么办?

2024-10-01 07:44:33 发布

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

我定义了一个有5个实例变量的类

class PassPredictData:
    def __init__(self, rating, name, lat, long, elev):
        self.rating = rating
        # rest of init code

我想确保:

  • rating是一个int
  • name是str
  • latlongelev是浮点数

当读取我的输入文件时,一切都会根据我的类创建一个对象列表。当我开始比较值时,我得到了奇怪的结果,因为实例变量仍然是字符串。在

在调用构造函数时使用int(string)float(string)创建对象时,转换值是“最python方式”还是应该使用类内的逻辑进行转换?在


Tags: 实例nameselfreststring定义initdef
3条回答

如果您在Python解释器中输入import this,您将得到“Python的Zen,by Tim Peters”。前三行似乎适用于您的情况:

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.

我建议您这样实现类:

^{pr2}$

这就是你在问题中提到的实现。它是简单的显式的。情人眼里出西施。在

对评论的回应

该实现对类的编写者来说是显式的,而其他一些解决方案则将类型转换隐藏在一些不透明的机制后面。在

有一个有效参数表明,从函数签名中看不出预期的参数类型是什么。但是,这个问题意味着所有参数都作为字符串传递。在这种情况下,所有构造函数参数的预期类型都是str。也许题目没有清楚地描述问题。也许更好的标题应该是“在将字符串作为参数传递给构造函数时强制执行实例变量类型”。在

就个人而言,我会在将值传递给构造函数之前进行任何字符串解析,除非解析是类的一个(或一个)明确声明的责任。我宁愿我的程序失败,因为我没有显式地转换一个值,而不是过于灵活,最终陷入类似于0 == "0"的Javascript情形。也就是说,如果你想接受字符串作为参数,你只需在构造函数中根据需要调用int(my_parameter)或{},这将确保这是数字,不管你传递的是数字、字符串还是布尔值。在

如果您想了解Python中的类型安全性的更多信息,可以看看type annotations,它由{a2}之类的类型检查器支持,而{a3}在类属性中用于类型安全。在

EDIT:(编辑,因为问题的主题已更改)我不建议在初始化时转换参数类型。例如:

class PassPredictData:
    def __init__(self, rating, name, lat, long, elev):
        self.rating = int(rating)
        self.name = str(name)
        ...

在我看来,这种隐式转换是危险的,原因不多。在

  1. 隐式地将参数类型转换为另一种类型而不发出警告是非常误导的
  2. 如果用户传入不需要的类型,则不会引发任何异常。这与隐式铸造密切相关。使用显式类型检查可以避免这种情况。在
  3. 静默转换类型违反了duck类型

与其转换参数类型,最好在初始化时检查参数类型。这种方法可以避免上述三个问题。为了实现这一点,您可以使用typedecorator中的强类型检查,因为它简单而且非常可读

对于Python2[编辑:根据操作请求将其作为参考]

^{pr2}$

对于Python3,可以使用注释语法

class PassPredictData1:
    @typed
    def __init__(self : object, rating : int, name : str, lat : float, long : float, elev : float):
        self.rating = rating

setup_typecheck()    
x = PassPredictData1(1, 5, 4, 9.8, 7.6)

引发错误:

TypeError: argument name = 5 doesn't match signature str

相关问题 更多 >