当我浏览生锈文档时,这一切都始于,并注意到在锈语中,与结构本身分开定义。要理解我的意思,请参见从Rust文档中提取的示例。
#[derive(Debug)]
struct Rectangle {
width: u32,
height: u32,
}
impl Rectangle {
fn area(&self) -> u32 {
self.width * self.height
}
}
多么不错的功能!我告诉自己。然后我开始在Python中考虑这个。
我们可以在Python中做同样的事情吗?
简短的答案是肯定的,尽管我们需要编写一些代码以使这种样式在Python中成为可能。这是一个简单的解决方案,借助装饰师和猴子斑点。
def impl(cls):
def wrapper(fn):
setattr(cls, fn.__name__, fn)
return fn
return wrapper
这是一个简单的用法。 dataclass
在这里用来类似于rust struct
,因为python中没有struct
。
from dataclasses import dataclass
@dataclass
class Rectangle:
width: int
height: int
@impl(Rectangle)
def area(self: Rectangle) -> int:
return self.height * self.width
if __name__ == "__main__":
rect = Rectangle(width=10, height=20)
print(rect.area())
area
方法的定义现在不在类定义。
用例
我认为这种样式提供了一些可以在我们未来的Python项目中使用的用例。
分开的实现模块
在某些情况下,实施方法还需要其他一些可能很大且进口缓慢的依赖项。使用此样式,您可以具有类定义和多个实现文件。开发人员仅导入他们想要使用的内容。
功能切换
使用此样式,我们可以具有功能切换,可以在不同的实现之间进行选择。看看以下示例。
def impl(cls: T, condition: bool=True):
def wrapper(fn):
if condition:
setattr(cls, fn.__name__, fn)
return fn
return wrapper
请注意,定义方法时执行上述条件,而不是在调用该方法时执行。
from dataclasses import dataclass
from enum import IntFlag, auto
@dataclass
class Rectangle:
width: int
height: int
class FeatureFlag(IntFlag):
FAST_AREA = auto()
@impl(FeatureFlag)
def read_from_config():
return FeatureFlag.FAST_AREA
实现文件对area
方法有两个定义,并且这两个方法通过功能标志控制。
FLAGS = FeatureFlag.read_from_config()
@impl(Rectangle, FeatureFlag.FAST_AREA in FLAGS)
def area(self: Rectangle) -> int:
return self.height * self.width
@impl(Rectangle, FeatureFlag.FAST_AREA not in FLAGS)
def area(self: Rectangle) -> int:
area_value = 0
for _ in range(self.width):
area_value += self.height
return area_value
if __name__ == "__main__":
rect1 = Rectangle(width=10, height=20)
print(rect1.area())
问题
在python中进行这种黑客攻击,例如mypy
。
我想使用编程语言,使编程更有趣。
如果您可以在评论中分享您的想法/想法,这将不胜感激。