有什么方法可以将这个Java代码翻译成Python吗?
class Foo
{
final static private List<Thingy> thingies =
ImmutableList.of(thing1, thing2, thing3);
}
例如
thingies
是属于 Thingy
类而不是其实例的 Foo
对象的不可变私有列表。
我知道如何从这个问题定义静态类变量Python中的静态类变量但我不知道如何使它们不可变和私有。
在 Python 中,约定是在属性名称上使用
_
前缀表示 protected
,使用 __
前缀表示 private
。这不是由语言强制执行的;而是由语言强制执行的。程序员应该知道不要编写依赖于非公开数据的代码。
如果你真的想强制不变性,你可以使用元类[docs](类的类)。只需修改
__setattr__
和 __delattr__
即可在有人尝试修改它时引发异常,并将其设为 tuple
(不可变列表)[docs]。
class FooMeta(type):
"""A type whose .thingies attribute can't be modified."""
def __setattr__(cls, name, value):
if name == "thingies":
raise AttributeError("Cannot modify .thingies")
else:
return type.__setattr__(cls, name, value)
def __delattr__(cls, name):
if name == "thingies":
raise AttributeError("Cannot delete .thingies")
else:
return type.__delattr__(cls, name)
thing1, thing2, thing3 = range(3)
class Foo(object):
__metaclass__ = FooMeta
thingies = (thing1, thing2, thing3)
other = [1, 2, 3]
print Foo.thingies # prints "(0, 1, 2)"
Foo.thingies = (1, 2) # raises an AttributeError
del Foo.thingies # raise an AttributeError
Foo.other = Foo.other + [4] # no exception
print Foo.other # prints "[1, 2, 3, 4]"
从技术上讲,仍然可以通过类的内部属性
.__dict__
来修改这些内容,但这应该足以阻止大多数用户,完全保护 Python 对象是非常困难的。
你无法在 Python 中完成这些事情,无论如何,这与你在 Java 中所做的不同。
按照约定,带有下划线前缀的名称被认为是私有的,不应在实现之外访问,但 Python 中没有强制执行此约定。它更多地被认为是一个警告,表明您正在搞乱实现细节,该细节可能会在代码的未来版本中毫无警告地更改。
您可以通过使用属性使其不可写(与不可变略有不同),但无法将其设为私有——这违背了Python的哲学。
class Foo(object): # don't need 'object' in Python 3
@property
def thingies(self):
return 'thing1', 'thing2', 'thing3'
f = Foo()
print f.thingies
#('thing1', 'thing2', 'thing3')
f.thingies = 9
#Traceback (most recent call last):
# File "test.py", line 8, in <module>
# f.thingies = 9
#AttributeError: can't set attribute
是否不可变取决于你返回的内容;如果您返回一个可变对象,您可能能够改变该对象,并让这些更改显示在实例/类中。
class FooMutable(object):
_thingies = [1, 2, 3]
@property
def thingies(self):
return self._thingies
foo = FooMutable()
foo.thingies.append(4)
print foo.thingies
# [1, 2, 3, 4]
这会让你改变
thingies
,并且由于返回的对象与实例/类中保存的对象相同,因此更改将反映在后续访问中。
比较一下:
class FooMutable(object):
@property
def thingies(self):
return [1, 2, 3]
foo = FooMutable()
foo.thingies.append(4)
print foo.thingies
# [1, 2, 3]
由于每次都会返回一个全新的列表,因此对其的更改不会反映在后续访问中。
property()
函数。它允许您为类的成员属性定义自己的自定义 Getter 和 Setter。它可能看起来像这样:
class myClass(object):
_x = "Hard Coded Value"
def set_x(self, val): return
def get_x(self): return self._x
def del_x(self): return
x = property(get_x, set_x, del_x, "I'm an immutable property named 'x'")
我还没有充分使用它来确定它是否可以用来创建“私有”的东西,所以你必须自己深入研究,但是
isinstance
可能会有所帮助。
final
部分。正如其他人所说,
__
很好地实现了private
方面,所以from typing import List
from typing_extensions import Final
class Foo:
__thingies: Final[List[Thingy]] = ImmutableList.of(thing1, thing2, thing3)
我将
ImmutableList
的定义留给你。一个
tuple
可能就可以了。*通常的警告是用户可以忽略它们
的答案的不同风格,在我看来更干净,并且还在 IDE 中提供了类型提示(假设使用 mypy)。
from typing import Final # (optional Final): Final is not enforced, but this provide a nice hint in IDE (assuming mypy is used)
class Immutable(type):
def __setattr__(cls, attr, value):
raise AttributeError("Cannot reassign members.")
def __delattr__(cls, name):
raise AttributeError("Cannot delete members.")
class ImmutableConstant(metaclass=Immutable):
FOO: Final = 1 # (optionnal Final)
这是一个运行时示例:
print(ImmutableConstant.FOO) # Prints '1'
try:
ImmutableConstant.FOO = 3 # Nice IDE warning (assuming mypy is used: Cannot assign to final attribute "FOO" mypy)
except AttributeError as e:
print(e) # Cannot reassign members.
try:
del ImmutableConstant.FOO
except AttributeError as e:
print(e) # Cannot delete members.