python类中的不可变属性和类型检查

我正在寻找一种方式在python中建立python类:

  • setter在分配之前检查值的类型
  • 不可能添加新的类属性
  • 目前我发现了这两个装饰者:

    
        def getter_setter_gen(name, type_):
            def getter(self):
                return getattr(self, "__" + name)
            def setter(self, value):
                print "setter", 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 = {}
            print "auto_attr_check", cls.__dict__.items()
            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:
            n = type(cls)(cls.__name__, cls.__bases__, new_dct)
            return n
    
    

    
        def froze_it(cls):
            def frozensetattr(self, key, value):
                print key
                key = ''+key
                print(dir(self))
                print key
                if not hasattr(self, key):
                    raise TypeError("Class {} is frozen. Cannot set {} = {}"
                      .format(cls.__name__, key, value))
                else:
                    object.__setattr__(self, key, value)
            cls.__setattr__ = frozensetattr
            return cls
    
    

    但我加入这两种方法有很多麻烦。 你可以帮我吗? 你有想法吗? 非常感谢


    你遇到的问题是你的property使用setattr来设置你的属性的值,但是你已经覆盖了__setattr__ ,以至于它不能成功。 hasattr检查将对主属性名称和属性下面的实际属性的下划线前缀名称(如果setter代码可以得到那么多)都会失败。

    我建议两个补充修复。 首先,将hasattr检查更加小心一点。 如果失败,它还应该检查属性对象的类字典:

        def frozensetattr(self, key, value):
            if not hasattr(self, key) and type(cls.__dict__.get(key)) is not property:
                raise TypeError("Class {} is frozen. Cannot set {} = {}"
                  .format(cls.__name__, key, value))
            else:
                object.__setattr__(self, key, value)
    

    第二个解决方案是setter函数,它应该绕过基础属性的__setattr__方法:

        def setter(self, value):
            print "setter", value
            if not isinstance(value, type_):
               raise TypeError("%s attribute must be set to an instance of %s" % (name, type_))
            object.__setattr__(self, "__" + name, value)
    

    最后要注意的:由您创建的属性名称的双下划线前缀property是不会调用名字改编,我怀疑它你打算什么。 名称修改只发生在编译时。 当一个方法包含__bar的名称时,该名称将被编译器转换为_NameOfTheClass__bar (其中NameOfTheClass是该方法在其中定义的类的名称)。

    在运行时,代码的行为就像直接在源代码中编写的名称一样。 这意味着__setattr__和朋友不会以任何特殊的方式处理损坏的名称(或双下划线前缀名,如果它们被编写为常规变量名而不是字符串,则会被编译器破坏)。 所以没有简单的方法来对动态创建的变量进行名称修改。

    如果你只是想让你的名字被非正式地标记为私有的(也就是说,它们不是公共API的一部分),你应该使用一个前导下划线。

    链接地址: http://www.djcxy.com/p/56431.html

    上一篇: Immutable attribute in python class and type check

    下一篇: Python readline Auto