如何强制/确保类属性是特定类型? [英] How to force/ensure class attributes are a specific type?
问题描述
如何在Python中将类成员变量限制为特定类型?
How do I restrict a class member variable to be a specific type in Python?
更长的版本:
我有一个类,该类具有几个在类外部设置的成员变量。由于它们的使用方式,它们必须为特定类型,即int或list。
I have a class that has several member variables which are set externally to the class. Due to the way they're used, they must be of specific types, either int or list.
如果这是C ++,我只是将它们设为私有并输入-检查设置功能。鉴于这是不可能的,是否有任何方法可以限制变量的类型,以便在为其分配了错误类型的值时在运行时发生错误/异常?还是我需要在使用它们的每个函数中检查它们的类型?
If this was C++, I would simply make them private and do type-checking in the 'set' function. Given that that isn't possible, is there any way to restrict the type of the variables so that an error/exception occurs at runtime if they're assigned a value of incorrect type? Or do I need to check their type within every function that uses them?
推荐答案
您可以像其他答案一样使用属性它-
因此,如果您要约束单个属性,例如说 bar,
并将其约束为整数,则可以编写如下代码:
You can use a property like the other answers put it - so, if you want to constraina single attribute, say "bar", and constrain it to an integer, you could write code like this:
class Foo(object):
def _get_bar(self):
return self.__bar
def _set_bar(self, value):
if not isinstance(value, int):
raise TypeError("bar must be set to an integer")
self.__bar = value
bar = property(_get_bar, _set_bar)
这有效:
>>> f = Foo()
>>> f.bar = 3
>>> f.bar
3
>>> f.bar = "three"
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 6, in _set_bar
TypeError: bar must be set to an integer
>>>
(还有一种新的属性写入方式,即使用内置的属性装饰器作为getter方法的修饰符-但我更喜欢旧方法,就像我上面提到的那样。)
(There is also a new way of writing properties, using the "property" built-in as a decorator to the getter method - but I prefer the old way, like I put it above).
当然,如果您的类上有很多属性,并且想要为了以这种方式保护所有人,它开始变得冗长。不用担心-Python的自省功能允许创建一个类装饰器,该装饰器可以用最少的行来实现自动化。
Of course, if you have lots of attributes on your classes, and want to protect all of them in this way, it starts to get verbose. Nothing to worry about - Python's introspection abilities allow one to create a class decorator that could automate this with a minimum of lines.
def getter_setter_gen(name, type_):
def getter(self):
return getattr(self, "__" + name)
def setter(self, value):
if not isinstance(value, type_):
raise TypeError("%s attribute must be set to an instance of %s" % (name, type_))
setattr(self, "__" + name, value)
return property(getter, setter)
def auto_attr_check(cls):
new_dct = {}
for key, value in cls.__dict__.items():
if isinstance(value, type):
value = getter_setter_gen(key, value)
new_dct[key] = value
# Creates a new class, using the modified dictionary as the class dict:
return type(cls)(cls.__name__, cls.__bases__, new_dct)
您只需要使用 auto_attr_c heck
作为类装饰器,并声明您要在类主体中的
属性也等于该属性也需要约束的类型:
And you just use auto_attr_check
as a class decorator, and declar the
attributes you want in the class body to be equal to the types the attributes need to constrain too:
...
... @auto_attr_check
... class Foo(object):
... bar = int
... baz = str
... bam = float
...
>>> f = Foo()
>>> f.bar = 5; f.baz = "hello"; f.bam = 5.0
>>> f.bar = "hello"
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 6, in setter
TypeError: bar attribute must be set to an instance of <type 'int'>
>>> f.baz = 5
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 6, in setter
TypeError: baz attribute must be set to an instance of <type 'str'>
>>> f.bam = 3 + 2j
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 6, in setter
TypeError: bam attribute must be set to an instance of <type 'float'>
>>>
这篇关于如何强制/确保类属性是特定类型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!