代码之家  ›  专栏  ›  技术社区  ›  A. Bykov

如何在Python类中生成抽象保护字段?

  •  3
  • A. Bykov  · 技术社区  · 6 年前

    from abc import ABCMeta, abstractmethod, abstractproperty
    import re
    
    def get_field_protector(*names):
        def check_attributes(cls):
            for t in names:
                if not hasattr(cls, t):
                    raise Exception('Abstract field "{0}" have to be defined'.format(t))
        def decorate_new_method(inp_method, class_name):
            def inner(cls, *args, **kwargs):
                if cls.__new__.decorated==class_name:
                    check_attributes(cls)
                return inp_method(cls, *args, **kwargs)
            return inner
        class result_protector(ABCMeta):
            def __setattr__(self, name, value):
                if name in names:
                    raise Exception("Read only class attribute!")
                super(self.__class__, self).__setattr__(name, value)
            def __delattr__(self, name):
                if name in names:
                    raise Exception("Read only class attribute!")
                super(self.__class__, self).__delattr__(name)
            def __init__(self, name, bases, attributes):
                super(self.__class__, self).__init__(name, bases, attributes)
                if not hasattr(self.__new__, 'decorated'):
                    self.__new__=decorate_new_method(self.__new__, name)
                    self.__new__.decorated=name
        return result_protector 
    

    在我开始使用以下类之前,它一直都很好:

    class test(object, metaclass=get_field_protector("essential_field")):
        essential_field="some_value"
        def __init__(self, val):
            self.val=val
    

    当我尝试创建这样的类时,我收到:

    >>> test(1)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "/media/bykov/9016-4EF8/main_architecture.py", line 13, in inner
        return inp_method(cls, *args, **kwargs)
    TypeError: object() takes no parameters
    
    1 回复  |  直到 6 年前
        1
  •  1
  •   C14L    6 年前

    布鲁诺的评论是正确的。在Python中,不能“保护”父类的属性,只需用两个带前缀的下划线来命名它。在你的例子中 __essential_field . 那就意味着把它留给任何正派人士。