Python - 使用 class 启用点符号
Python - Using a class to enable dot notation
正在处理具有子属性的 class。下面的代码是一个好的实践/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
在大多数常见的高级语言中,点符号用于指示命名空间。 Python也是如此。以下面无用的class为例:
>>> 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 的 类 以及它们的工作原理。
我会建议使用正确的工具来完成工作——如果我希望我的 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)
正在处理具有子属性的 class。下面的代码是一个好的实践/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
在大多数常见的高级语言中,点符号用于指示命名空间。 Python也是如此。以下面无用的class为例:
>>> 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 的 类 以及它们的工作原理。
我会建议使用正确的工具来完成工作——如果我希望我的 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)