定义@属性
Defining @property
我在具体 class 中使用 @property
定义 getter 时遇到问题。这是 python 代码:
from abc import ABCMeta, abstractproperty
class abstract(object):
__metaclass__ = ABCMeta
def __init__(self, value1):
self.v1 = value1
@abstractproperty
def v1(self):
pass
class concrete(abstract):
def __init__(self, value1):
super(concrete, self).__init__(value1)
@property
def v1(self):
return self.v1
然后测试代码,得到这个错误:
test_concrete = concrete("test1")
test_concrete.v1
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-190-eb896d7ec1c9> in <module>()
----> 1 test_concrete = concrete("test1")
2 test_concrete.v1
<ipython-input-189-bf15021022d3> in __init__(self, value1)
11 class concrete(abstract):
12 def __init__(self, value1):
---> 13 super(concrete, self).__init__(value1)
14
15 @property
<ipython-input-189-bf15021022d3> in __init__(self, value1)
3
4 def __init__(self, value1):
----> 5 self.v1 = value1
6
7 @abstractproperty
AttributeError: can't set attribute
基本上我打算将v1
设置为只读属性。
我习惯于对属性和它的getter函数使用相同的名称,但是如果class继承自抽象class,我似乎不能这样做。
我找到了一个变通方法,方法是对 getter 函数 v1
使用与 get_v1
不同的名称:
class abstract(object):
__metaclass__ = ABCMeta
def __init__(self, value1):
self.v1 = value1
@abstractproperty
def get_v1(self):
pass
class concrete(abstract):
def __init__(self, value1):
super(concrete, self).__init__(value1)
@property
def get_v1(self):
return self.v1
这个问题有更好的解决方法吗?
您的问题与摘要无关类。这是一个名称空间问题; 属性 对象和实例属性占用相同的名称空间,您不能让实例属性和 属性 使用完全相同的名称。
您正在尝试使用 self.v1 = ...
访问 属性 并且 v1
并不是神奇的实例属性,只是因为您正在访问它来自实例的方法,即 always 将成为 属性 对象。
同理,你的属性getter会导致死循环:
@property
def v1(self):
return self.v1
因为 self.v1
是 属性 对象,而不是实例属性。
为实际存储使用不同的名称:
def __init__(self, value1):
self._v1 = value1
@property
def v1(self):
return self._v1
请注意,您不能在 Python 中拥有真正的私有属性(就像在 C# 或 Java 中一样);名称上的前导下划线只是一种约定,坚定的编码人员始终可以直接访问您的实例状态。 property
对象不会改变这一点。
我在具体 class 中使用 @property
定义 getter 时遇到问题。这是 python 代码:
from abc import ABCMeta, abstractproperty
class abstract(object):
__metaclass__ = ABCMeta
def __init__(self, value1):
self.v1 = value1
@abstractproperty
def v1(self):
pass
class concrete(abstract):
def __init__(self, value1):
super(concrete, self).__init__(value1)
@property
def v1(self):
return self.v1
然后测试代码,得到这个错误:
test_concrete = concrete("test1")
test_concrete.v1
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-190-eb896d7ec1c9> in <module>()
----> 1 test_concrete = concrete("test1")
2 test_concrete.v1
<ipython-input-189-bf15021022d3> in __init__(self, value1)
11 class concrete(abstract):
12 def __init__(self, value1):
---> 13 super(concrete, self).__init__(value1)
14
15 @property
<ipython-input-189-bf15021022d3> in __init__(self, value1)
3
4 def __init__(self, value1):
----> 5 self.v1 = value1
6
7 @abstractproperty
AttributeError: can't set attribute
基本上我打算将v1
设置为只读属性。
我习惯于对属性和它的getter函数使用相同的名称,但是如果class继承自抽象class,我似乎不能这样做。
我找到了一个变通方法,方法是对 getter 函数 v1
使用与 get_v1
不同的名称:
class abstract(object):
__metaclass__ = ABCMeta
def __init__(self, value1):
self.v1 = value1
@abstractproperty
def get_v1(self):
pass
class concrete(abstract):
def __init__(self, value1):
super(concrete, self).__init__(value1)
@property
def get_v1(self):
return self.v1
这个问题有更好的解决方法吗?
您的问题与摘要无关类。这是一个名称空间问题; 属性 对象和实例属性占用相同的名称空间,您不能让实例属性和 属性 使用完全相同的名称。
您正在尝试使用 self.v1 = ...
访问 属性 并且 v1
并不是神奇的实例属性,只是因为您正在访问它来自实例的方法,即 always 将成为 属性 对象。
同理,你的属性getter会导致死循环:
@property
def v1(self):
return self.v1
因为 self.v1
是 属性 对象,而不是实例属性。
为实际存储使用不同的名称:
def __init__(self, value1):
self._v1 = value1
@property
def v1(self):
return self._v1
请注意,您不能在 Python 中拥有真正的私有属性(就像在 C# 或 Java 中一样);名称上的前导下划线只是一种约定,坚定的编码人员始终可以直接访问您的实例状态。 property
对象不会改变这一点。