我在python中寻找一种在python中构建类的方法:
目前我找到了这两个装饰者:
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
但加入这两种方法我有很多麻烦。 你能帮助我吗?你有想法吗? 非常感谢
答案 0 :(得分:1)
您遇到的问题是,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)
检查更改为更加小心。如果失败,它还应该检查属性对象的类dict:
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__
是定义方法的类的名称)。
在运行时,代码的行为就像被破坏的名称直接写在源代码中一样。这意味着public void methodName(value 1, value 2)
{
var query = this.table
join that.table on this.table.column equals that.table.column
where column equals column
}
和朋友不会处理任何特殊类型的错误名称(或编译器会被编译器修改的双下划线前缀名称,如果它们被编写为常规变量名而不是字符串)办法。因此,没有简单的方法可以对动态创建的变量进行名称修改。
如果您只是希望将您的名称非正式地标记为私有(即,它们不属于公共API),您应该使用单个前导下划线。