没有args的setter方法名称的Python命名约定

时间:2019-01-16 21:58:53

标签: python naming conventions

我一直在用类编写python代码,这些类具有一种称为:

def set_log_paths(self):

问题是,此方法不带参数,而是根据self的其他值确定应该使用哪些值。在这种情况下使用“ set”一词不合适吗?我问是因为它不是直接的获取器或设置器,就像在带有私人成员的语言中使用的那样。

方法名称中是否有一个常用的常规单词?

1 个答案:

答案 0 :(得分:1)

如果您没有传递任何值,而是在调用方法的时刻根据当前值计算值,则描述该动作的动词是“更新”是合理的,因此{{1} }。

只需仔细检查一下您是否真的需要这种设计,以及您/您的班级其他用户有什么机会忘记调用这些“更新”方法?

Python的自省很容易允许采用“ reactive programing”中的某些元素,当它们依赖的值更改时,这些元素可用于触发这些更新程序方法。

这种体系结构的最佳选择是为属性设置一个描述符,该属性在调用update_log_paths()时将检查一个类级注册表以“查看”是否应触发事件,然后一个装饰器启用您列出将触发它的属性。具有正确的__set__方法的基类可以设置所有内容。

让我们假设您将类的“基础属性”作为类主体中的带注释的属性-可以使用的描述符,装饰器和基类代码可能与以下内容类似:

__init_subclass__

让我们开始工作吧

from functools import wraps
from collections import ChainMap

class EventDescriptor:
    def __init__(self, name, default):
        self.name = name
        self.default = default
    def __get__(self, instance, owner):
        if not instance:
            return self
        return instance.__dict__[self.name] if self.name in instance.__dict__ else self.default
    def __set__(self, instance, value):
        instance.__dict__[self.name] = value
        triggers = instance._post_change_registry.get(self.name, [])
        for trigger in triggers:
            getattr(instance, trigger)()


def triggered_by(*args):
    def decorator(func):
        func._triggered_by = args
        return func
    return decorator


class EventPropertyMixin:
    def __init_subclass__(cls, **kw):
        super.__init_subclass__(**kw)
        for property_name, type_ in cls.__annotations__.items():
            if not hasattr(cls, property_name):
                raise TypeError("Properties without default values not supported in this example code")
            # It would also be trivial to implement runtime type-checking in this point (and on the descriptor code)
            setattr(cls, property_name, EventDescriptor(property_name, getattr(cls, property_name)))
        # collects all registries in ancestor-classes, preserving order:
        post_change_registry = ChainMap()
        for ancestor in cls.__mro__[:0:-1]:
            if hasattr(ancestor, "_post_change_registry"):
                post_change_registry = post_change_registy.new_child(ancestor._post_change_registry)
        post_change_registry = post_change_registry.new_child({})
        for method_name, method in cls.__dict__.items():
            if callable(method) and hasattr(method, "_triggered_by"):
                for property_name in method._triggered_by:
                    triggers = post_change_registry.setdefault(property_name, [])
                    if method_name not in triggers:
                        triggers.append(method_name)
        cls._post_change_registry = post_change_registry


class Test(EventPropertyMixin):
    path1: str = ""
    path2: str = ""

    @triggered_by("path1", "path2")
    def update_log_paths(self):
        self.log_paths = self.path1 + self.path2

所以,这是复杂的代码,但是通常位于框架或基本实用程序库中的代码-拥有这50行代码,您可能会使用Python为您工作, 并使用它来调用更新方法,因此它们的名称完全无关紧要! :-) (好吧,这段代码对于所问的问题来说是过大了-但是我今晚想睡觉之前会产生这样的东西-免责声明:我没有测试这里涉及的与继承相关的极端情况)