Python 如何在设置/检索属性时自动转义属性?

Python 如何在设置/检索属性时自动转义属性?,python,Python,我正在寻找一种在设置某些属性时执行一些自定义转义的方法,以及在从我的一个对象检索这些属性时执行相应的取消转义代码的方法。我已经看过了uuuu setattr uuuuuuuuuuu getattr uuuuuuuuuuuu和uuuuuuu getattribute uuuuuuuuuuu,但看不到它们与属性的关系 例如,我有一个类,例如: class Bundle(object): def __init__(self): self.storage = Storage()

我正在寻找一种在设置某些属性时执行一些自定义转义的方法,以及在从我的一个对象检索这些属性时执行相应的取消转义代码的方法。我已经看过了uuuu setattr uuuuuuuuuuu getattr uuuuuuuuuuuu和uuuuuuu getattribute uuuuuuuuuuu,但看不到它们与属性的关系

例如,我有一个类,例如:

class Bundle(object):
    def __init__(self):
        self.storage = Storage()

    @property
    def users_name(self):
        """
        Get the user's name
        """
        return self.storage.users_name

    @users_name.setter
    def users_name(self, users_name):
        """
        Set the user's name
        """
        # only permit letters and spaces. 
        if not re.match('^[A-Za-z ]+$', users_name):
            msg = "'%s' is not a valid users_name. It must only contain letters and spaces" % users_name
            log.fatal(msg)
            raise ConfigurationError(msg)

        self.storage.users_name = users_name
    ...
对象上有几个这样的属性

我想要的是一个方法,它只会影响我的一些属性(如users_name,但不影响“storage”),并在设置/检索时转义/取消转义该值

  • __getattr\uuuu似乎不正确,因为应该为新的和现有的属性调用此代码
  • __setattr\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。例如,是否总是调用u u setattr_uuuu而不是我的自定义方法?如何从_usetattr_;中调用自定义方法?是否有一种简单的方法可以只影响my@property属性而不存储要处理的属性列表
  • __getattribute_u;我尝试过使用它,但最终导致无限循环。除此之外,我的问题与_usetattr_uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
  • 最好的方法是什么

    --更新--

    详细说明:此特定的“Bundle”类充当代理,将配置值存储在不同的后端-在本例中是包装ConfigParser的FileConfigBackend。ConfigParser使用“%”符号进行插值。但是,我要设置的某些值可以合法地包含百分号,因此我需要对其进行转义。但是,不是转义,而是转义为每个属性显式调用它们,我希望有某种神奇的方法,每次设置属性时都会调用它。然后它将对字符串运行
    replace('%','%')
    。同样,我希望有一种方法,每次检索属性时都会在返回它之前对值运行
    replace('%','%')

    另外,由于“Bundle”中的大多数属性只是代理到后端存储,如果有一种方法可以说“如果属性在这个列表中,只需调用
    self.storage.property_NAME=VALUE
    ”,那就好了。有时候,尽管我希望能够覆盖该赋值,例如对要设置的值运行正则表达式

    所以,实际上,我在寻找一种方式来表示“当设置属性时,始终调用此方法。然后,如果存在具体的@property.setter,则调用它,而不是执行
    self.storage.key=value


    (doh!我的意思是uuu getattr uuuuuuuuu&uuuuu setattr uuuuuuuuuuuuuu不是uuuuuuu get uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu

    阅读谷歌叔叔在这方面的建议,到试验结束时,所有错误都变得非常清楚。在您的情况下,您可能不需要
    \uuu getatribute\uuuuuuuuuuuuuuuuuu
    ,因为它是在访问时调用的,而不是查看obect的
    \uuuuuuuuu dict

    我不习惯使用装饰器,因为使用
    property()
    内置对我来说更清楚:


    方法
    \uuuu set\uuuu()
    \uuu get\uuuu()
    用于描述符类,这意味着您需要为属性定义类。很好的示例:


    实际上,您可能要查找的是通过覆盖类中的
    \uuuuSetAttr\uuuuuuuuu()
    \uuuuuuuuuGetAttr()\uuuuuuuuuuu
    方法(如果从2.7.x中的
    对象
    派生,则可用)来访问的属性:


    属性装饰器按照协议创建一个对象,
    \uuuuuu get\uuuuuu
    \uuuu set\uuuuuu
    方法在该协议下活动

    我能想到的向某些属性添加其他行为的最佳方法是创建 您自己的装饰器。此装饰器将遵循相同的协议,包装最初由Python创建的属性,并添加所需的转义/取消转义行为。这将允许您将“特殊”转义属性标记为:

    @escaped
    @property
    def users_name(self):
      ...
    
    只有这些属性才会得到特殊处理。下面是一个如何实现这一点的快速示例:

    class escaped:
      def __init__(self, property_to_wrap):
        # we wrap the property object created by the other decorator
        self.property = property_to_wrap
    
      def __get__(self, instance, objtype=None):
        # delegate to the original property
        original_value = self.property_to_wrap.__get__(instance, objtype)
        # ... change the data however you like
        return frotz(original_value)
    
      def __set__(self, instance, new_value):
        actual_value = frob(new_value)
        self.property.__set__(instance, actual_value)
    
      ...
    
    对于所有描述符方法都应该重复相同的操作。您还必须将
    属性本身的
    getter
    setter
    deleter
    方法委托给
    属性本身(以允许您在包装属性中使用
    @users\u name.setter
    等语法。您可以查看以获取帮助


    这里也可以找到一些细节:。

    我使用装饰师提供了一个不同的答案,但是如果你真的喜欢使用神奇的方法,有一种方法:

    class Magic(object):
        @staticmethod
        def should_be_escaped(property_name):
            return not "__" in property_name
    
        def __getattribute__(self, property):
            value = object.__getattribute__(self, property)
            if Magic.should_be_escaped(property):
                value = value.replace("%%", "%")
            return value
    
        def __setattr__(self, property, value):
            if Magic.should_be_escaped(property):
                value = value.replace("%", "%%")
            object.__setattr__(self, property, value)
    
    调用
    object.\uuuuu getattribute\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu和
    object.\uuuuuuuuu setattr\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu

    这是一个更糟糕的解决方案,原因在于
    是否应该转义
    ,您必须根据名称决定是否应该转义属性。这很难正确执行,而且您必须关心特殊名称、存储
    变量等


    例如,上面的
    should\u escape
    的实现非常不完整,它将尝试在对象的方法上调用
    replace
    ,因此应该为属性类型添加一个检查。有很多这样的情况。这就是为什么我建议将decorator解决方案作为cleaner-它显式地标记谁收到了这种特殊的行为,并且没有令人不快的意外后果。

    你几乎永远不想使用
    \uuuu getattribute\uuuu
    。相反,使用
    \uu getattr\uuuuuu
    。区别在于总是调用
    \uu getattr\uuuuuu
    ,而
    \uu getattr\uuuuuuuuu>只为缺少属性而调用