创建一个类的最方便的方法是哪些实例的属性不能从类外部更改(你仍然可以获得值),所以它是可能的在类的方法中调用self.var = v
,而不是在类之外调用ClassObject().var = v
?
我已尝试弄乱__setattr__()
,但如果我覆盖它,则无法在name
方法中启动__init__()
属性。唯一的办法就是覆盖__setattr__()
并使用我现在正在做的object.__setattr__()
:
class MyClass(object):
def __init__(self, name):
object.__setattr__(self, "name", name)
def my_method(self):
object.__setattr__(self, "name", self.name + "+")
def __setattr__(self, attr, value):
raise Exception("Usage restricted")
现在这个解决方案有效,而且已经足够了,但我想知道是否有更好的解决方案。这个问题是:我仍然可以从课堂外的任何地方拨打object.__setattr__(MyClass("foo"), "name", "foo_name")
。
有没有办法完全阻止将变量设置为来自课外的任何东西?
编辑:愚蠢的我没有提到我在这里找不到property
,你们中的一些人已经回答过了,但这对我来说还不够,因为它会离开{{1}可变的。
答案 0 :(得分:3)
不,你不能在纯python中做到这一点。
您可以使用属性将属性标记为只读;使用下划线前缀'private'属性代替:
class Foo(object):
def __init__(self, value):
self._spam = value
@property
def spam(self):
return self._spam
以上代码仅指定属性的getter; Python现在不允许您为Foo().spam
设置值:
>>> class Foo(object):
... def __init__(self, value):
... self._spam = value
... @property
... def spam(self):
... return self._spam
...
>>> f = Foo('eggs')
>>> f.spam
'eggs'
>>> f.spam = 'ham'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: can't set attribute
当然,您仍然可以从外部访问“私人”_spam
属性:
>>> f._spam
'eggs'
>>> f._spam = 'ham'
>>> f.spam
'ham'
您可以使用双下划线约定,其中在编译时重命名开头(但不是最后!)的__
属性名称。这不是为了使属性无法从外部访问,而是旨在保护属性不被子类覆盖。
class Foo(object):
def __init__(self, value):
self.__spam = value
@property
def spam(self):
return self.__spam
您仍然可以访问这些属性:
>>> f = Foo('eggs')
>>> f.spam
'eggs'
>>> f.__spam
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Foo' object has no attribute '__spam'
>>> f._Foo__spam
'eggs'
>>> f._Foo__spam = 'ham'
>>> f.spam
'ham'
答案 1 :(得分:2)
没有严格的方法在Python上进行封装。您可以做的最好的事情是将2个下划线__
添加到预期的私有属性中。这将导致它们被类名(_ ClassName _AttribName)破坏,因此如果您尝试在继承的类上使用它们,则不会引用基本成员。如果您使用getattrib()
或setattrib()
,则不会损坏名称。
您也可以覆盖__dir()__
以隐藏它们。
答案 2 :(得分:2)
您可以使用属性来模拟这种行为,但像Martijn所说,可以直接访问变量。 这样做是一个你不理解Python哲学的信号,请查看。
Why Python is not full object-oriented?
物业方式:
http://docs.python.org/2/library/functions.html#property
class C(object):
def __init__(self):
self._x = None
def getx(self):
return self._x
def setx(self, value):
raise Exception("Usage restricted")
x = property(getx, setx)