2024-04-24 15:30:05 发布
网友
有没有办法把这个Java代码转换成Python?
class Foo { final static private List<Thingy> thingies = ImmutableList.of(thing1, thing2, thing3); }
例如,thingies是属于Foo类而不是其实例的Thingy对象的不可变私有列表。
thingies
Foo
Thingy
我知道如何从这个问题Static class variables in 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]
因为每次都会返回一个全新的列表,所以对它的更改不会反映在后续的访问中。
在Python中,惯例是在属性名上使用_前缀表示protected,使用__前缀表示private。这不是由语言强制的;程序员应该知道不要编写依赖于非公共数据的代码。
_
protected
__
private
如果您真的想强制执行不变性,那么可以使用元类[docs](类的类)。只要修改__setattr__和__delattr__以在有人试图修改它时引发异常,并将其设为tuple(不可变列表)[docs。
__setattr__
__delattr__
tuple
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对象。
.__dict__
你不能在Python中做这两件事,至少在Java中不能。
按照惯例,以下划线为前缀的名称被视为私有名称,不应在实现外部访问,但Python中的任何内容都不强制执行此约定。这被认为是一个警告,说明您正在处理一个实现细节,在未来的代码版本中可能会在没有警告的情况下发生更改。
通过使用属性可以使它不可写(与不可变有细微的不同),但是没有办法使它私有化——这违背了Python的哲学。
它是否是不可变的取决于您返回的内容;如果您返回一个可变的对象,您可能能够对和进行变异,使这些更改显示在实例/类中。
这将允许您对
thingies
进行变异,并且由于返回的对象与实例/类中保留的对象相同,因此更改将反映在后续访问中。比较一下:
因为每次都会返回一个全新的列表,所以对它的更改不会反映在后续的访问中。
在Python中,惯例是在属性名上使用
_
前缀表示protected
,使用__
前缀表示private
。这不是由语言强制的;程序员应该知道不要编写依赖于非公共数据的代码。如果您真的想强制执行不变性,那么可以使用元类[docs](类的类)。只要修改
__setattr__
和__delattr__
以在有人试图修改它时引发异常,并将其设为tuple
(不可变列表)[docs。示例
从技术上讲,仍然可以通过类的内部
.__dict__
属性来修改这些属性,但这应该足以阻止大多数用户,很难完全保护Python对象。你不能在Python中做这两件事,至少在Java中不能。
按照惯例,以下划线为前缀的名称被视为私有名称,不应在实现外部访问,但Python中的任何内容都不强制执行此约定。这被认为是一个警告,说明您正在处理一个实现细节,在未来的代码版本中可能会在没有警告的情况下发生更改。
相关问题 更多 >
编程相关推荐