在这个例子中,我想避免# Oops
可能性。
def foo():
return "foo"
class MyClass(object):
def __init__(self):
setattr(self, 'foo', foo)
def bar(self):
return "bar"
-
>>> x = MyClass()
>>> x.foo()
>>> x.foo = 2 # Oops
>>> x.foo()
TypeError: 'int' object is not callable
如何防止我的方法被错误覆盖?
答案 0 :(得分:2)
使x.foo
成为属性,而不指定setter。然而,动态地完成它是非常棘手的:
def add_property(inst, name, method):
'''
Adds a property to a class instance.
Property must be added to the CLASS.
'''
cls = type(inst)
if not hasattr(cls, '__perinstance'):
cls = type(cls.__name__, (cls,), {})
cls.__perinstance = True
inst.__class__ = cls
setattr(cls, name, property(method))
然后而不仅仅是setattr
这样做:
class MyClass(object):
def __init__(self):
add_property(self, 'foo', lambda _ : 2)
(为了更实际的使用,请将lambda
函数替换为
函数或方法返回foo
)
输出:
>>> o=MyClass()
>>> o.foo
2
>>> o.foo=3
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: can't set attribute
>>>
答案 1 :(得分:1)
您可以检查传递给setattr
属性名称是否已经存在于类中(如果需要,还有实例)__dict__
并且在这种情况下不要重写它:
class MyClass(object):
def __setattr__(self, name, value):
if name not in self.__class__.__dict__ and name not in self.__dict__:
super(MyClass, self).__setattr__(name, value)
试验:
>>> x = MyClass()
>>> x.foo = foo # equal to your __init__ setattr call
>>> x.foo()
'foo'
>>> x.foo = 2
>>> x.foo()
'foo'