做组合别名的最pythonic和正确的方法是什么?
这是一个假设的场景:
class House:
def cleanup(self, arg1, arg2, kwarg1=False):
# do something
class Person:
def __init__(self, house):
self.house = house
# aliases house.cleanup
# 1.
self.cleanup_house = self.house.cleanup
# 2.
def cleanup_house(self, arg1, arg2, kwarg1=False):
return self.house.cleanup(arg1=arg1, arg2=arg2, kwarg1=kwarg1)
Run Code Online (Sandbox Code Playgroud)
AFAIK 与 #1 我测试的编辑器理解这些和 #2 一样好 - 自动完成、文档字符串等。
#1 方法有什么缺点吗?从python的角度来看,哪种方式更正确?
扩展方法 #1 unsettable 和类型提示的变体将不受评论中指出的所有问题的影响:
class House:
def cleanup(self, arg1, arg2, kwarg1=False):
"""clean house is nice to live in!"""
pass
class Person:
def __init__(self, house: House):
self._house = house
# aliases
self.cleanup_house = self.house.cleanup
@property
def house(self):
return self._house
Run Code Online (Sandbox Code Playgroud)
第一种方法有很多问题:
house一个property,但对于不需要它的东西来说,这是一项重要的工作。有关示例实现,请参阅此答案的结尾。cleanup_house不会被继承。在类中定义的函数对象是一个非数据描述符,可以被继承和覆盖,也可以绑定到一个实例。类中根本不存在第一种方法中的实例属性。它是一个绑定方法的事实是偶然的。super().cleanup_house对于一个具体的例子,子类将无法访问。person.cleanup_house.__name__ != 'cleanup_house'. 这不是您经常检查的内容,但是当您这样做时,您会期望函数名称是cleanup.好消息是您不必多次重复签名即可使用方法#2。Python 提供了非常方便的 splat ( *)/splatty-splat ( **) 表示法,用于将所有参数检查委托给被包装的方法:
def cleanup_house(self, *args, **kwargs):
return self.house.cleanup(*args, **kwargs)
Run Code Online (Sandbox Code Playgroud)
就是这样。所有常规和默认参数都按原样传递。
这就是 #2 是迄今为止更 Pythonic 的方法的原因。除非您复制方法签名,否则我不知道它将如何与支持类型提示的编辑器交互。
可能有问题的一件事cleanup_house.__doc__是与house.cleanup.__doc__. 这可能值得转换house为 a property,其 setter 分配cleanup_house.__doc__。
要解决问题 1.(但不是 2. 或 3.),您可以house使用 setter 作为属性实现。这个想法是在house属性更改时更新别名。一般来说,这不是一个好主意,但这里是您在问题中所拥有的替代实现,它可能会更好地工作:
class House:
def cleanup(self, arg1, arg2, kwarg1=False):
"""clean house is nice to live in!"""
pass
class Person:
def __init__(self, house: House):
self.house = house # use the property here
@property
def house(self):
return self._house
@house.setter
def house(self, value):
self._house = house
self.cleanup_house = self._house.cleanup
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
216 次 |
| 最近记录: |