Python - 使用类启用点表示法

时间:2015-10-09 17:57:31

标签: python class syntax

处理具有子属性的类。以下代码是一个很好的做法/ Pythonic?如果没有,有什么建议吗?

目标

exp = ExCls()
prop1 = exp.subprop.prop1
exp.print_prop2()
## prop1 = 1
## prints 2

示例代码

class ExCls():
   class subprop:
      prop1 = 1
      prop2 = 2
   def print_prop2(self):
      print self.subprop.prop2

2 个答案:

答案 0 :(得分:2)

在大多数常见的高级语言中,点表示法用于表示命名空间。 Python也是如此。以下面的无用类为例:

>>> class UselessClass(object):
...     @property
...     def and_on(self):
...         return self
...     def forever(self):
...         return "I can see into forever"
>>> this_goes_on = UselessClass()
>>> this_goes_on.and_on.and_on.and_on.and_on.and_on.forever()
'I can see into forever'

它正在做的就是返回它自己(UselessClass类型的实例化对象),它可以访问它自己的所有属性。

您的代码唯一的问题是,正如GingerPlusPlus指出的那样,您在subprop的所有实例之间共享ExCls。这可能是期望的,但(基于问题)也可能不是。以下是为什么这很糟糕的一个例子:

>>> test1 = ExCls()
>>> test2 = ExCls()
>>> test1.subprop.prop1
1
>>> test2.subprop.prop1 = 2
>>> test1.subprop.prop1
2

正如您所看到的,这通常不是您期望的行为。相反,你可能要做的是:

class ExCls(object):
    def __init__(self):
        class subprop:
            prop1 = 1
            prop2 = 2
        self.subprop = subprop()

    def print_prop2(self):
        print(self.subprop.prop2)

总的来说,我强烈建议您回过头来阅读Python的课程,以及它们的工作原理。

答案 1 :(得分:1)

我建议使用正确的工具来完成工作 - 如果我希望我的subprop只包含一些数据,我会使用types.SimpleNamespace

from types import SimpleNamespace

class Useless:
    def __init__(self):
        self.subprop = SimpleNamespace(prop1=1, prop2=2)

或者,它是足够接近的不可变兄弟,collections.namedtuple

from collections import namedtuple

class Useless:
    Subprop = namedtuple('Subprop', 'prop1, prop2')
    def __init__(self):
        # two lines below does the same, choose more readable one
        self.subprop = Subprop(1, 2)
        self.subprop = Subprop(prop1=1, prop=2)

如果我想让它也包含一些方法,我会使用简单的自定义对象:

class Useless:
    class Subprop:
        def __init__(self, prop1, prop2):
            self.prop1 = prop1
            self.prop2 = prop2
        def sum(self):
            return self.prop1 + self.prop2
    def __init__(self):
        # two lines below does the same, choose more readable one
        self.subprop = Subprop(1, 2)
        self.subprop = Subprop(prop1=1, prop2=2)