我有一个简单的类(Node
),它具有一个ID和3个坐标(X,Y,Z)。它的ID必须是整数,并且其坐标是浮动的,因此我使用了以下类定义。
我是OO编程的新手,但是对于这样一个简单的类来说似乎“繁重”。有没有什么办法来压缩这一点,使它少重复?例如,如果我有10个坐标,这将是比较重。
无论如何,我只是想知道是否有更好的方法可以做到这一点。
class Node():
def __init__(self):
self.ID = 0
self.X = 0
self.Y = 0
self.Z = 0
@property
def ID(self):
return self._ID
@ID.setter
def ID(self,value):
self._ID = int(value)
@property
def X(self):
return self._X
@X.setter
def X(self,value):
self._X = float(value)
@property
def Y(self):
return self._Y
@Y.setter
def Y(self,value):
self._Y = float(value)
@property
def Z(self):
return self._Z
@Z.setter
def Z(self,value):
self._Z = float(value)
答案 0 :(得分:0)
你想要的是一个自定义的描述符,而不是property
本身。
class Force(object):
def __init__(self, type_, var):
self.type = type_
self.var = "_" + var
def __get__(self, obj, type):
# obj is None when the descriptor is accessed via
# the class, rather than an instance.
# type is the class through which the descriptor is accessed;
# not used here.
if obj is None:
return self
return getattr(obj, self.var)
def __set__(self, obj, value):
setattr(obj, self.var, self.type(value))
class Node:
ID = Force(int, 'ID')
X = Force(float, 'X')
Y = Force(float, 'Y')
Z = Force(float, 'Z')
def __init__(self):
self.ID = 0
self.X = 0
self.Y = 0
self.Z = 0
Python 3.6添加了对__set_name__
方法的支持,该方法在实例化描述符时会自动调用,并接收将描述符分配给其的名称作为参数。
class Force:
def __init__(self, type_):
self.type = type_
def __set_name__(self, owner, name):
# Owner is the class which contains the descriptor;
# not used here
self.var = "_" + name
def __get__(self, obj, type):
if obj is None:
return self
return getattr(obj, self.var)
def __set__(self, obj, value):
setattr(obj, self.var, self.type(value))
class Node:
ID = Force(int)
X = Force(float)
Y = Force(float)
Z = Force(float)
def __init__(self):
self.ID = 0
self.X = 0
self.Y = 0
self.Z = 0
(我敢肯定这可以改善。Force.__init__
可以为描述符的每个实例取一个初始值,而不是要求Node.__init__
对其进行初始化。)
答案 1 :(得分:0)
在Python中,如果要提供对属性的读写访问,只需将它们设为“公共”即可。
像这样:
class Node():
def __init__(self):
self.ID = 0 # No underscores
self.X = 0 # means
self.Y = 0 # public
self.Z = 0 # (by convention)
现在你可以使用你的类是这样的:
n = Node()
n.Z = 9
这很好,因为您仍然可以稍后决定调整读取和写入操作的行为(使用@property装饰器),而无需制动类的接口。
您可能还想研究dataclasses(在Python 3.7中引入):
from dataclasses import dataclass
@dataclass
class Node:
ID = 0
X = 0
Y = 0
Z: float = 0 # type hints are optional
最后一点:类属性按惯例是小写的。只有常量应该使用完整的大写字母写。