【问题标题】:Python - Using a class to enable dot notationPython - 使用类启用点表示法
【发布时间】:2015-10-09 17:57:30
【问题描述】:

处理具有子属性的类。下面的代码是一个好习惯/ 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

【问题讨论】:

  • 请注意subpropExCls 的所有实例之间共享,这是故意的吗?
  • 您应该通读Tutorial 几遍,然后看看property 内置的函数,也许还可以看看Descriptor How To Guide
  • @GingerPlusPlus,我在构建时忽略了这个事实。谢谢。
  • @wwii,感谢 property 参考。这会很有帮助:)

标签: python class syntax


【解决方案1】:

在大多数常见的高级语言中,点符号用于指示命名空间。 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 指出的那样,您正在使 subpropExCls 的所有实例之间共享。这可能是需要的,但(基于问题)也可能不是。这是一个为什么不好的例子:

>>> 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 的类以及它们的工作原理。

【讨论】:

  • 谢谢@Rejected 我已经开导了。
【解决方案2】:

我建议使用正确的工具来完成这项工作 - 如果我希望我的 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)

【讨论】:

  • 非常有趣的@GingerPlusPlus...也感谢您的意见! :)
猜你喜欢
  • 1970-01-01
  • 2017-01-20
  • 2018-09-05
  • 1970-01-01
  • 1970-01-01
  • 2021-11-18
  • 1970-01-01
  • 2011-08-06
  • 2016-02-03
相关资源
最近更新 更多