强制python类成员变量为特定类型 [英] Force python class member variable to be specific type

查看:1045
本文介绍了强制python类成员变量为特定类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何在Python中将类成员变量限制为特定类型?






p>

我有一个类,它有几个成员变量,在外部设置类。由于它们的使用方式,它们必须是特定类型,即int或list。如果这是C ++,我会简单地使它们私有,并在'set'函数中进行类型检查。假定这是不可能的,有没有任何方式来限制变量的类型,以便在运行时发生错误/异常,如果他们被分配一个不正确的类型的值?或者,我需要在使用它们的每个函数中检查它们的类型吗?



谢谢。

解决方案

您可以使用像其他答案的属性 -
所以,如果你想约束单个属性,说bar,
并将其限制为一个整数,你可以编写如下代码:

  class Foo(object):
def _get_bar(self):
return self .__ bar
def _set_bar(self,value):
如果不是isinstance(value,int):
raise TypeError(bar必须设置为整数)
self .__ bar = value
bar = property(_get_bar,_set_bar)

 >>> f = Foo()
>>>> f.bar = 3
>>>> f.bar
3
>>>> f.bar =three
回溯(最近最后一次调用):
在< module>中第1行的文件< stdin&
文件< stdin>,第6行,在_set_bar
TypeError:bar必须设置为整数
>>

(还有一种新的写入属性的方法,使用内置的属性装饰器到getter方法 - 但我喜欢旧的方式,就像我把它放在上面)。



当然,如果你有很多属性在你的类,以这种方式保护他们,它开始获得详细。没有什么可担心的 - Python的内省能力允许我们创建一个类装饰器,可以用最少的行自动化这个。

  def getter_setter_gen(name,type_):
def getter(self):
return getattr(self,__+ name)
def setter(self,value):
isinstance(value,type_):
raise TypeError(%s属性必须设置为%s的实例%(name,type_))
setattr(self,__+ name,value )
返回属性(getter,setter)

def auto_attr_check(cls):
new_dct = {}

if isinstance(value,type):
value = getter_setter_gen(key,value)
new_dct [key] = value
#创建一个新类,类dict:
return type(cls)(cls .__ name__,cls .__ bases__,new_dct)

您只需使用 auto_attr_check 作为类装饰器,并在类体中声明所需的
属性等于属性需要的类型约束太:

  ... 
... @auto_attr_check
... class Foo ):
... bar = int
... baz = str
... bam = float
...
>>> f = Foo()
>>>> f.bar = 5; f.baz =hello; f.bam = 5.0
>>>> f.bar =hello
回溯(最近一次调用):
在< module>中第1行的文件< stdin&
文件< stdin>,第6行,在setter中
TypeError:bar属性必须设置为< type'int'
>>>> f.baz = 5
回溯(最近最后一次调用):
在< module>中第1行的文件< stdin&
文件< stdin>,第6行,在setter中
TypeError:baz属性必须设置为< type'str'>
>>>> f.bam = 3 + 2j
回溯(最近一次调用最后):
在< module>中的文件< stdin&
文件< stdin>,第6行,在setter中
TypeError:bam属性必须设置为< type'float'>
>>>>


How do I restrict a class member variable to be a specific type in Python?


Longer version:

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. 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?

Thanks.

解决方案

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)

And this works:

>>> 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
>>> 

(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).

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)

And you just use auto_attr_checkas 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'>
>>> 

这篇关于强制python类成员变量为特定类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆