将实例字段转换为属性
Convert Instance Fields into Properties
我想将对象的所有实例字段转换为属性(仅限 getter),以便使它们成为只读的。这些字段可能由子类定义。
我怎样才能做到这一点?
class SomeClass(object):
def __init__(self, foo, bar):
self.foo = foo
self.bar = bar
convert_all_instance_fields_into_properties(self) # implementation ?
Python中没有"private"这样的东西。如果你想并且足够努力,你可以提取任何东西。
有2个等级semi-private:
- 一个供内部使用的下划线前缀,通常在外部可访问 - 但大多数 IDE 会在其下划线并警告不推荐的做法
- pseudo-private 的两个下划线前缀,如果有人真的想要它仍然可以访问但丑陋
大多数时候,您只需要一个下划线 - 人们只有在认为真正需要它时才会访问它。
在我正在使用的代码中,我看到两个下划线仅用作封装延迟加载属性的一种方式(一个下划线是 "getter" 并检查变量是否已加载)。
请记住,即使使用 "getter",您也将是 return 一个对象,除非您自己 return 一个副本。重新考虑您的设计,考虑 Python,而不是 "private" 和 "getters"。 ;)
编辑:
好像我误解了问题。
用 @property
装饰器标记的函数将 return 不带括号调用它们(spam.eggs
,而不是 spam.eggs()
)并且是 "read-only"(您可以做 bacon = spam.eggs
但不做 spam.eggs = bacon
).
但我的其余评论仍然有效:
- 只要有足够的决心,一切都触手可及
- 使用下划线礼貌地要求人们不要访问该值
- 如果您的 getter 属性 return 是一个可变对象,它在内部仍然是可变的(只有引用会保持不变),例如
eggs.list = []
不行,但是 eggs.list.append("spam")
可以!
可以很容易地使用 python 内置函数实现只读字段:
class X:
def __init__(self, val):
self.foo = val
def __setattr__(self, key, value):
if not hasattr(self, key): # only for first set
super(X, self).__setattr__(key, value)
else:
raise ValueError
def main():
x = X('bar')
y = X('baz')
assert x.foo == 'bar'
assert y.foo == 'baz'
# raises ValueError
x.foo = 'Raise an error!'
如果要指定哪些字段是只读的
class X:
readonly = ['foo']
def __init__(self, val):
self.foo = val
def __setattr__(self, key, value):
if key in self.readonly and not hasattr(self, key):
super(X, self).__setattr__(key, value)
else:
raise ValueError
我想将对象的所有实例字段转换为属性(仅限 getter),以便使它们成为只读的。这些字段可能由子类定义。
我怎样才能做到这一点?
class SomeClass(object):
def __init__(self, foo, bar):
self.foo = foo
self.bar = bar
convert_all_instance_fields_into_properties(self) # implementation ?
Python中没有"private"这样的东西。如果你想并且足够努力,你可以提取任何东西。
有2个等级semi-private:
- 一个供内部使用的下划线前缀,通常在外部可访问 - 但大多数 IDE 会在其下划线并警告不推荐的做法
- pseudo-private 的两个下划线前缀,如果有人真的想要它仍然可以访问但丑陋
大多数时候,您只需要一个下划线 - 人们只有在认为真正需要它时才会访问它。
在我正在使用的代码中,我看到两个下划线仅用作封装延迟加载属性的一种方式(一个下划线是 "getter" 并检查变量是否已加载)。
请记住,即使使用 "getter",您也将是 return 一个对象,除非您自己 return 一个副本。重新考虑您的设计,考虑 Python,而不是 "private" 和 "getters"。 ;)
编辑:
好像我误解了问题。
用 @property
装饰器标记的函数将 return 不带括号调用它们(spam.eggs
,而不是 spam.eggs()
)并且是 "read-only"(您可以做 bacon = spam.eggs
但不做 spam.eggs = bacon
).
但我的其余评论仍然有效:
- 只要有足够的决心,一切都触手可及
- 使用下划线礼貌地要求人们不要访问该值
- 如果您的 getter 属性 return 是一个可变对象,它在内部仍然是可变的(只有引用会保持不变),例如
eggs.list = []
不行,但是eggs.list.append("spam")
可以!
可以很容易地使用 python 内置函数实现只读字段:
class X:
def __init__(self, val):
self.foo = val
def __setattr__(self, key, value):
if not hasattr(self, key): # only for first set
super(X, self).__setattr__(key, value)
else:
raise ValueError
def main():
x = X('bar')
y = X('baz')
assert x.foo == 'bar'
assert y.foo == 'baz'
# raises ValueError
x.foo = 'Raise an error!'
如果要指定哪些字段是只读的
class X:
readonly = ['foo']
def __init__(self, val):
self.foo = val
def __setattr__(self, key, value):
if key in self.readonly and not hasattr(self, key):
super(X, self).__setattr__(key, value)
else:
raise ValueError