当前位置: 首页 > 知识库问答 >
问题:

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

公冶安怡
2023-03-14

我正在寻找一种在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

但我很难加入这两种方法。你能帮助我吗?你有什么想法吗?谢谢

共有1个答案

谈炳
2023-03-14

您遇到的问题是,您的属性正在使用setattr来设置属性的值,但是您已经覆盖了\uuuu setattr\uuuuu,因此它永远不会成功。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函数,它应该绕过底层属性的\uuuu setattr\uuuu方法:

    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)

最后一点注意:由属性创建的属性名称上的双下划线前缀不会调用名称损坏,我怀疑这是您的意图。名称损坏只发生在编译时。当一个方法包含一个类似于\uuuuu bar的名称时,编译器会将该名称转换为\uu类的名称\uuuu bar(其中类的名称是定义该方法的类的名称)。

在运行时,代码的行为与直接在源代码中写入损坏的名称完全相同。这意味着\uuuuu setattr\uuuuuuu和朋友们不会以任何特殊方式处理损坏的名称(或双下划线前缀的名称,如果它们是作为常规变量名而不是字符串编写的,编译器可能会损坏这些名称)。因此,在动态创建的变量上没有简单的方法进行名称损坏。

如果您只是希望您的名字被非正式地标记为私有(也就是说,它们不是公共应用编程接口的一部分),您可能应该使用一个前导下划线。

 类似资料:
  • 本文向大家介绍Python的可变类型和不可变类型?相关面试题,主要包含被问及Python的可变类型和不可变类型?时的应答技巧和注意事项,需要的朋友参考一下 可变数据类型:列表、字典、可变集合 不可变数据类型:数字、字符串、元组、不可变集合    

  • 问题内容: 我对什么是不可变类型感到困惑。我知道该float对象被认为是不可变的,在我的书中有这样的例子: 由于类的结构/层次结构,这是否被认为是不可变的?意思float是在类的顶部,是它自己的方法调用。类似于此类示例(即使我的书说的dict是可变的): 可变的东西在类内部具有方法,例如以下类型: 另外,对于最后一个,如果我将这种类型的set传递给它: 不调用该example方法,它返回一个字典。

  • 问题内容: 我需要一种检查类的方法,以便可以安全地标识哪些属性是用户定义的类属性。问题是,像DIR功能(),inspect.getmembers()和朋友返回所有类的属性包括预定义的像:,,,。这当然是可以理解的,并且可以说我可以列出一个要忽略的命名成员列表,但是不幸的是,这些预定义属性必定会随着不同版本的Python发生变化,因此使我的项目在python项目中容易发生变化- 我不喜欢那样。 例:

  • 问题内容: 我有以下课程: 这可以按预期工作(使用字符串的单词而不是字母来初始化集合)。但是,当我想对set的不可变版本执行相同操作时,该方法似乎被忽略: 我可以达到类似的目的吗? 问题答案: 是的,您需要重写特殊方法: 输出为:

  • 问题内容: 我正在尝试学习可变/不可变的类,而我遇到了这篇文章 提供的部分答案是: 如果要强制不变性,则不能有子类。例如,请参见java.lang.String,由于这个原因,它是最终类:为了防止人们将String子类化以使其可变。 好的,我了解, 但是 ,您将如何处理此问题。假设您的任务是创建3个Employee类,Accountant,ITDepartment和QualityAssurance