python-3.x - 类实例上的 delattr 产生意外的 AttributeError

标签 python-3.x attributes

我有以下用于配置实现的抽象基类(简称):

class Config():
    """
    Configuration file binding
    """   
    def __init__(self, path):
        """
        Initialize the config file
        """
        path = path if path.endswith(self.__SUFFIX) else path + self.__SUFFIX
        self.__file = ConfigFile(path)
        self.__defaults = self.dict()

    @property    
    def fields(self):
        """
        Returns a list of fields
        """
        return [field for field in self.dict()]

    def dict(self):
        """
        Determine existing fields
        """
        return {field:getattr(self, field) 
                for field in dir(self) 
                if field.upper() == field 
                and not field.startswith('_')}

    def reset(self):
        """
        Reset the file to the default values
        """
        self.__clear()
        return self.__load(self.__defaults)

    def __load(self, d):
        """
        Load data from file
        """
        for field in d:
            if field.upper() == field:
                setattr(self, field, self.__decode(d[field]))

    def __clear(self):
        """
        Remove all fields
        """
        print('My fields: ', end='')    # XXX: Debug
        print(self.fields)  # XXX: Debug
        print('My attributes: ', end='')    # XXX: Debug
        print(dir(self))    # XXX: Debug
        for field in self.fields:
            print('Removing field: ' + field)
            delattr(self, field)

    <SNIP>

这是由我的程序的系统范围配置实现的:

class __Sysconfig(Config):
    """
    H.O.M.I.E.'s system configuration
    """
    ### Application information ###
    APP_NAME = 'H.O.M.I.E.'
    APP_VER = '0.1-indev'
    APP_FULL_NAME = "Cool system"

    ### System logging ###
    LOG_DIR = '/var/log/homie.d'
    LOGFILE = '/var/log/homie'
    LOGLVL = 2

    ### System files ###
    DAEMON_SERVICES_FILE = '/var/run/homie.services'
    DAEMON_SOCK = 'tcp://127.0.0.1'
    GLOBAL_CONFIG_DIR = '/usr/local/etc/homie.d'

    ### System EMail ###
    EMAIL_FROM = 'homie@company.com'
    TECH_EMAIL = 'me@company.com'
    ADMIN_EMAILS = ['me@company.com', 'other@company.com']

    def __init__(self):
        """
        Creates a sysconfig instance
        """
        super().__init__('/usr/local/etc/homie')

然后由以下方式初始化:

sysconfig = __Sysconfig()
sysconfig.reset()

但是,这会产生以下错误(使用 Config() 的打印输出进行调试):

My fields: ['EMAIL_FROM', 'APP_VER', 'LOG_DIR', 'GLOBAL_CONFIG_DIR', 'TECH_EMAIL', 'DAEMON_SERVICES_FILE', 'ADMIN_EMAILS', 'APP_NAME', 'LOGFILE', 'APP_FULL_NAME', 'DAEMON_SOCK', 'LOGLVL']
My attributes: ['ADMIN_EMAILS', 'APP_FULL_NAME', 'APP_NAME', 'APP_VER', 'DAEMON_SERVICES_FILE', 'DAEMON_SOCK', 'EMAIL_FROM', 'GLOBAL_CONFIG_DIR', 'LOGFILE', 'LOGLVL', 'LOG_DIR', 'TECH_EMAIL', '_Config__SUFFIX', '_Config__TYPES', '_Config__clear', '_Config__decode', '_Config__defaults', '_Config__encode', '_Config__file', '_Config__lbi', '_Config__lei', '_Config__load', '_Config__ls', '_Config__ts', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'dict', 'exists', 'fields', 'lbi', 'lei', 'load', 'loaded', 'ls', 'reload', 'remove', 'reset', 'store', 'ts']
Removing field: EMAIL_FROM
Traceback (most recent call last):
  File "/etc/init.d/retard", line 3, in <module>
    from homie.init import __main__
  File "/usr/lib/python3.4/site-packages/homie/init/__main__.py", line 20, in <module>
    from ..api import Customer, Service
  File "/usr/lib/python3.4/site-packages/homie/api/__init__.py", line 12, in <module>
    from .abc import CAC
  File "/usr/lib/python3.4/site-packages/homie/api/abc.py", line 14, in <module>
    from ..homie import sysconfig
  File "/usr/lib/python3.4/site-packages/homie/homie.py", line 50, in <module>
    sysconfig.reset()
  File "/usr/lib/python3.4/site-packages/homie/lib/config.py", line 114, in reset
    self.__clear()
  File "/usr/lib/python3.4/site-packages/homie/lib/config.py", line 159, in __clear
    delattr(self, field)
AttributeError: EMAIL_FROM

为什么delattr()找不到属性?

最佳答案

在定义子类__Sysconfig(Config)的时候,python显然是把属性绑定(bind)到类上的。实例 self 可以访问它们,但不能删除它们。

delattr(self, field) 更改为 delattr(self.__class__, field) 成功了!

关于python-3.x - 类实例上的 delattr 产生意外的 AttributeError,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25054729/

相关文章:

python-3.x - 最简单的 python 链接缩短器

c# - 为什么要在代码中使用 'custom attributes' (.NET)

java - 如何判断 Selenium for Java 中是否选中了一个复选框?

c# - 向 json.net 添加自定义属性

c# - 属性是否可以禁止目标类实现公共(public)构造函数?

Python - 通过模块属性(按字符串名称)访问类实例

python - pickle OrderedDict 的子类

python-3.x - Python - 自定义采样以获取训练和测试数据

python - chat() 缺少 1 个必需的位置参数 : 'id'

python-3.x - 基于自定义列表对数据框中的列进行排序