Python中的访问器/存储类 在C++中,我经常用“访问器”结构来分解大类,如下面的 struct Big { struct Coordinates { int x; int y; } coords; }

Python中的访问器/存储类 在C++中,我经常用“访问器”结构来分解大类,如下面的 struct Big { struct Coordinates { int x; int y; } coords; },python,oop,Python,Oop,这避免了名称空间污染,使调用站点非常清晰,例如:big.coords.x这尤其有助于避免使用许多名为“set_x”的函数,而这些函数会变为“set.x” 我想在Python中做同样的事情,比如下面,但我想知道这是否被认为是好的Python风格 class Big: class Coordinates: x = 0 y = 0 coords = Coordinates() big.coords.x 如果您从未实例化过类,则完全可以仅对名称空间进行

这避免了名称空间污染,使调用站点非常清晰,例如:
big.coords.x这尤其有助于避免使用许多名为“set_x”的函数,而这些函数会变为“set.x”

我想在Python中做同样的事情,比如下面,但我想知道这是否被认为是好的Python风格

class Big:
    class Coordinates:
        x = 0
        y = 0
    coords = Coordinates()

big.coords.x

如果您从未实例化过类,则完全可以仅对名称空间进行实例化:

class Colors:
    class RGB:
        Red = (255, 0, 0)
        Green = (0, 255, 0)
        Blue = (0, 0, 255)
    class CMYK:
        pass

color1 = Colors.RGB.Red
然而,这是不同的:

class Big:
    class Coordinates:
        x = 0
        y = 0
    coords = Coordinates()
Big
类中实例化
Coordinates
类对象,特别是在
Big.coords

x
y
在开始时对于每个
坐标
对象实例都是
0
。但它们也是类属性,而不是实例属性。这意味着它们在每个实例之间共享,直到您在实例中指定其中一个。然后该特定实例开始有自己的
x
y
。这与你所期望的完全不同。你应该这样做:

class Coordinates:
    def __init__(self, x=0, y=0):
        self.x = x
        self.y = y

class Big:
    def __init__(self, coords=None):
        self.coords = coords or Coordinates(0,0)

    def __str__(self):
        return "Big coords at x:{} y:{}".format(self.coords.x, self.coords.y)

big = Big()
print(big)
print(big.coords.x, big.coords.y)

point1 = Coordinates(1, 2)
big1 = Big(point1)
print(big1)
输出:

Big coords at x:0 y:0
0 0
Big coords at x:1 y:2
这样可以使一个实例包含另一种类型的实例。这也是使用包含而不是继承的一个示例

安排名称空间的另一种常见方法是,只在要导入的模块中组织名称


有关其他想法,请参阅。

在类实例中存储另一个类的实例是一件正常而有用的事情。实际上,将另一个类的定义嵌套在using类中,没有那么多。。。您是否真的不可能使用<代码>坐标< /代码>实例独立于<代码>大< /代码>?在这个例子中,代码>坐标< /COD>绝对是更通用的,但请考虑包含的类是特定于<代码>大< /代码>类的东西。在这种情况下,完全限定名清楚地说明了它们之间的关系。在Python中,这样做并不常见。
Big
的实例可能将
Coordinates
的实例作为属性,但只有在特殊情况下,
Coordinates
本身才是
Big
的属性。仅仅因为
坐标
仅由
Big
使用,并不使其成为
Big
的一部分。类不仅仅是语法。