我正在尝试在 python 中“模拟”命名空间。我使用内部和外部类层次结构来创建我的命名空间。例如,您希望将文件(如资源)的路径保存在一个位置。我试过这样的事情:
src = #path to source folder
class Resources:
root = src + "Resources\\"
class Fonts:
root = Resources.root + "fonts\\"
font1 = root + "font1.ttf"
font2 = root + "font2.ttf"
class Images:
root = Resources.root + "images\\"
logo = root + "logo"
image1= root + "image1"
class StyleSheets:
root = Resources.root + "stylesheets\\"
default = root + "default.qss"
class JsonData:
root = src + "Data\\"
class TableEntries:
root = JsonData.root
entries1 = root + "Entries1.json"
entries2 = root + "Entries2.json"
访问元素如下所示:
logoPath = Resources.Images.image1
不幸的是,由于以下错误,这不起作用:
root = Resources.root + "fonts\\"
NameError: name 'Resources' is not defined
我的问题
是否可以根据外部类的类变量设置内部类的类变量?如果没有,是否有另一种方法可以在不使用多个文件的情况下访问如上所示的元素?
最佳答案
Is it possible to set class variables of inner class based on class variables of outer class?
并非没有使用自定义元类来处理内部类,这肯定无助于可读性和可维护性(并且将 - 正确地 - 被任何有经验的 Python 程序员视为一个完整的 WTF)。
编辑:实际上对于您的示例片段,元类解决方案并不那么复杂,请参见此答案的结尾
原因是在 Python 中几乎所有事情都发生在运行时。
class
是一个可执行语句,并且类对象仅在整个类语句的主体结束后创建并绑定(bind)到它的名称。If not, is there another way to access the elements as shown above without using multiple files?
很简单(简单的例子):
import os
# use a single leading underscore to mark those classes
# as "private" (=> not part of the module's API)
class _Fonts(object):
def __init__(self, resource):
self.font1 = os.path.join(resource.root, "font1.ttf")
self.font2 = os.path.join(resource.root, "font2.ttf")
class _Resources(object):
def __init__(self, src):
self.root = os.path.join(rsc, "Ressources")
self.Fonts = _Fonts(self)
# then instanciate it like any other class
src = "/path/to/source/folder"
Resources = _Resources(src)
print(Resources.Fonts.font1)
编辑:经过更多思考,针对您的用例的基于元类的解决方案不会那么复杂(但这不会是任何通用的东西):
import os
class ResourcesMeta(type):
def __init__(cls, name, bases, attrs):
for name in attrs:
obj = getattr(cls, name)
if isinstance(obj, type) and issubclass(obj, SubResource):
instance = obj(cls)
setattr(cls, name, instance)
class SubResourceMeta(type):
def __new__(meta, name, bases, attrs):
if not bases:
# handle the case of the SubResource base class
return type.__new__(meta, name, bases, attrs)
root = attrs.pop("root")
cls = type.__new__(meta, name, bases, {})
cls._root = root
cls._attrs = attrs
return cls
class SubResource(metaclass=SubResourceMeta):
def __init__(self, parent):
self.root = os.path.join(parent.root, self._root)
for name, value in self._attrs.items():
setattr(self, name, os.path.join(self.root, value))
class Resources(metaclass=ResourcesMeta):
root = "/path/to/somewhere"
class Fonts(SubResource):
root = "fonts"
font1 = "font1.ttf"
font2 = "font2.ttf"
class Images(SubResource):
root = "images"
logo = "logo"
image1= "image1"
关于python - 名称间距 : How to set class variable of inner class based on class variable of outer class?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49320766/