python中的安全属性配置

2024-04-24 06:50:36 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个表示算法参数选项的类。创建对象会将所有选项初始化为某些预定义值。然后,我可以通过简单地为相应的属性指定不同的值来更改参数:

opts = AlgOptions()
opts.mutation_strength = 0.2

但是,有时在键入属性名称时会出错,例如:

opts = AlgOptions()
opts.mutation_str = 0.2

Python只是创建了一个不同的属性并继续运行,产生了难以调试的意外结果。你知道吗

有没有一个优雅的方法来避免这种潜在的陷阱?总是重复检查所有属性名感觉很枯燥,而像C#这样的语言会将这种情况解释为错误。我想起来的事情很少,但有一些注意事项:

1)我可以为参数创建setter方法,但这似乎是很多样板代码。这样,如果我试图用错误的名称调用一个方法,我将得到一个有意义的exepion。你知道吗

2)我可以创建类内所有属性的列表,并检查是否有名称不在列表中的类属性。但是,我不确定在什么地方和什么时候执行检查,而且这似乎是一个笨拙的解决方案。你知道吗


Tags: 方法名称算法列表参数键入属性选项
3条回答

所以一般来说,最好是避免打字错误;)但这里有一个(稍微有点黑)的解决方案。基本上是对NoSetAttr类进行子类化,并使用set_new_attr方法在类中设置新属性。你知道吗

class NoSetAttr:
    def __setattr__(self, attr, value):
        getattr(self, attr)  # will raise error if not found
        super().__setattr__(attr, value)
    def set_new_attr(self, attr, value):
        super().__setattr__(attr, value)

class ExampleClass(NoSetAttr):
    def __init__(self, x):
        self.set_new_attr('x', x)

inst = ExampleClass(12)
inst.x  # 12
inst.x = 23
inst.x  # 23
inst.y = 2  # raises attribute error

您可以将基类转换为类装饰器@no_set_attr,然后对类进行注释,这可能会更简单。你知道吗

您可以通过使用slots来实现这一点,这基本上可以防止创建未在__init__中声明的属性:

>>> class Foo:
...     __slots__ = ["bar", "baz"]
...     def __init__(self, bar, baz):
...         self.bar = bar
...         self.baz = baz
...
>>> foo = Foo(1, 2)
>>> foo.asdf = 1
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'Foo' object has no attribute 'asdf'
>>> foo.bar
1
>>> foo.bar += 5
>>> foo.bar
6

注意,使用__slots__有文档中讨论的一些缺点。你知道吗

以下是一种只允许设置某些属性的可能方法:

class AlgOptions():

    def __str__(self):
        return str(self.__dict__)

    def __setattr__(self, k, v):
        allowed = ('mutation_strength',)
        if k in allowed:
            self.__dict__[k] = v
        else:
            raise AttributeError(f"attribute {k} not allowed")


opts = AlgOptions()
opts.mutation_strength = 0.2
try:
    opts.mutation_str = 0.2
except Exception as e:
    print('Sorry about this:', e)

print(opts)

就我个人而言,我永远不会在我的代码中使用这样的东西。我不喜欢这种试图“对抗”语言的方法。。。记住,python不是c#。你知道吗

相关问题 更多 >