我有一个包含多个属性的类,每个属性都必须是一个数字。在一遍又一遍地重复相同的代码后,我认为有更多的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")
答案 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'