Python setter 不带参数的方法名称的命名约定
Python naming convention for setter method name without args
我一直在用 类 编写 python 代码,其中有一个方法叫做:
def set_log_paths(self):
事实是,此方法不带参数,它根据 self 的其他值确定某些值应该是什么。在这种情况下使用 "set" 这个词是不是不合适?我问是因为它不是直接的 getter 或 setter,因为人们会在具有私人成员的语言中使用它。
我的方法名称中是否有常用的约定词?
如果您不传递任何值,而是根据当前值计算调用该方法时的值,描述该操作的动词是 "update" 是合理的 - 因此update_log_paths()
.
仔细检查一下您是否真的需要这种设计,you/other 您的 class 用户忘记调用这些 "update" 方法的可能性有多大。
Python 的内省很容易允许采用“reactive programing”中的一些元素,当它们所依赖的值发生变化时,这些元素可用于触发这些更新方法。
这种架构的一个最佳选择是您的属性的描述符,在调用 __set__
后,如果应该触发事件,将检查 class 级别的注册表以 "see" ,然后是一个装饰器,使您能够列出将触发它的属性。具有适当 __init_subclass__
方法的基础 class 可以设置一切。
假设您将 class 上的 "base properties" 作为 class 正文中的注释属性 - 描述符、修饰符和基础-class 代码工作可能是一件好事:
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
让我们开始工作:
In [2]: t = Test()
In [3]: t.path1 = "/tmp"
In [4]: t.path2 = "/inner"
In [5]: t.log_paths
Out[5]: '/tmp/inner'
所以,这是复杂的代码,但代码通常位于框架内或基本实用程序库中 - 使用这 50 行代码,您可以使用 Python 来工作 for 你,让它调用更新方法,所以它们的名字根本不重要! :-)
(好的,这段代码对于所问的问题来说太过分了 - 但我今晚睡觉前有心情制作这样的东西 - 免责声明:我没有测试此处涵盖的与继承相关的角落案例)
我一直在用 类 编写 python 代码,其中有一个方法叫做:
def set_log_paths(self):
事实是,此方法不带参数,它根据 self 的其他值确定某些值应该是什么。在这种情况下使用 "set" 这个词是不是不合适?我问是因为它不是直接的 getter 或 setter,因为人们会在具有私人成员的语言中使用它。
我的方法名称中是否有常用的约定词?
如果您不传递任何值,而是根据当前值计算调用该方法时的值,描述该操作的动词是 "update" 是合理的 - 因此update_log_paths()
.
仔细检查一下您是否真的需要这种设计,you/other 您的 class 用户忘记调用这些 "update" 方法的可能性有多大。
Python 的内省很容易允许采用“reactive programing”中的一些元素,当它们所依赖的值发生变化时,这些元素可用于触发这些更新方法。
这种架构的一个最佳选择是您的属性的描述符,在调用 __set__
后,如果应该触发事件,将检查 class 级别的注册表以 "see" ,然后是一个装饰器,使您能够列出将触发它的属性。具有适当 __init_subclass__
方法的基础 class 可以设置一切。
假设您将 class 上的 "base properties" 作为 class 正文中的注释属性 - 描述符、修饰符和基础-class 代码工作可能是一件好事:
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
让我们开始工作:
In [2]: t = Test()
In [3]: t.path1 = "/tmp"
In [4]: t.path2 = "/inner"
In [5]: t.log_paths
Out[5]: '/tmp/inner'
所以,这是复杂的代码,但代码通常位于框架内或基本实用程序库中 - 使用这 50 行代码,您可以使用 Python 来工作 for 你,让它调用更新方法,所以它们的名字根本不重要! :-) (好的,这段代码对于所问的问题来说太过分了 - 但我今晚睡觉前有心情制作这样的东西 - 免责声明:我没有测试此处涵盖的与继承相关的角落案例)