pythonic方法将多个类实例属性声明为数字?

时间:2015-11-29 15:31:22

标签: python types properties initialization

我有一个包含多个属性的类,每个属性都必须是一个数字。在一遍又一遍地重复相同的代码后,我认为有更多的pythonic方法将多个类实例属性声明为数字。

现在我将每个属性值设置为None,如果该值设置为非数字类型,则引发类型错误。我倾向于在初始化属性时将属性类型设置为数字。

谢谢!

示例:

import numbers

class classWithNumbers(object):

    def __init__(self):
        self._numProp1 = None
        self._numProp2 = None

    @property
    def numProp1(self):
        return self._numProp1
    @numProp1.setter
    def numProp1(self,value):
        if not isinstance(value, numbers.Number): #repeated test for number
            raise TypeError("Must be number")

        self._numProp1 = value

    @property
    def numProp2(self):
        return self._numProp2
    @numProp2.setter
    def numProp(self,value):
        if not isinstance(value, numbers.Number):
            raise TypeError("Must be number")

        self._numProp2 = value

另外,我实际上已将其包装到每个属性设置器重复的方法中:

def isNumber(value):
if not isinstance(value, numbers.Number):
    raise TypeError("Must be number")

3 个答案:

答案 0 :(得分:1)

如果此类的每个属性都应为数字,则可以实现自定义__setattr__方法:

class ClassWithNumbers(object):

    def __init__(self):
        self.num_prop1 = 0
        self.num_prop2 = 0

    def __setattr__(self, name, value):
        if not isinstance(value, numbers.Number):
            raise TypeError("Must be number")
        super(ClassWithNumbers, self).__setattr__(name, value)

从文档中:尝试进行属性分配时调用__setattr__(is)。这被称为代替正常机制(即将值存储在实例字典中)。 name是属性名称,value是要分配给它的值。

更一般的方法是不允许更改一次分配属性的类型:

class ClassWithUnchangeableTypes(object):
    def __init__(self):
        self.num_prop1 = 0
        self.num_prop2 = 0

    def __setattr__(self, name, value):
        if hasattr(self, name):  # this means that we assigned value in the past
            previous_value_type = type(getattr(self, name))
            if not isinstance(value, previous_value_type):
                raise TypeError("Must be {}".format(previous_value_type))
        super(ClassWithUnchangeableTypes, self).__setattr__(name, value)

说到pythonic,来自pep8:

  

类名通常应使用CapWords惯例。

     

使用函数命名规则:小写,必要时用下划线分隔,以提高可读性。

答案 1 :(得分:0)

相当现代(python 3.5+)和pythonic方式正在使用type hints

@property
def numProp1(self):
    return self._numProp1
@numProp1.setter
def numProp1(self,value: int):
    self._numProp1 = value

更兼容的方法是尝试转换为int,如果失败,将为您抛出异常。它也可能有不受欢迎的行为,如接受浮动:

@property
def numProp1(self):
    return self._numProp1
@numProp1.setter
def numProp1(self,value):
    self._numProp1 = int(value)

但是你的实施已经没有任何问题了。 如果您不想显式声明getter和setter,可以在使用时检查它们的类型,而不是在分配时。

答案 2 :(得分:0)

最Pythonic方式可能是调用int构造函数并让它抛出异常:

class ClassWithNumbers(object):
    def __init__(self, v1, v2):
        self.numprop1 = int(v1)
        self.numprop2 = int(v2)

如果numprop是您界面的一部分,则创建@property访问者将是合适的。您还可以实现自己的描述符:

class Number(object):
    def __init__(self, val=0):
        self.__set__(self, val)

    def __get__(self, obj, cls=None):
        return self.val

    def __set__(self, obj, val):
        try:
            self.val = int(val)
        except ValueError as e:
            raise TypeError(str(e))

class ClassWithNumbers(object):
    numprop1 = Number(42)
    numprop2 = Number(-1)

用法:

c = ClassWithNumbers()
print c.numprop1
c.numprop1 += 1
print c.numprop1
c.numprop1 = 'hello'