Han*_*ave 4 python syntax design-patterns
通常,Python中的句点表示类成员身份:
class A:
a = 1
>>> A.a
1
Run Code Online (Sandbox Code Playgroud)
有时,语言似乎不够灵活,无法从计算机科学以外的领域完全表达一个想法.考虑下面的例子(为了简洁起见,相当简单)使用相同的运算符看起来像完全不同的东西.
class Vector:
def __init__(self, data):
self.data = list(data)
def dot(self, x):
return sum([a*b for a, b in zip(self.data, x.data)])
def __getattr__(self, x):
if x == 'Vector':
return lambda p: self.dot(Vector(p))
return self.dot(globals()[x])
Run Code Online (Sandbox Code Playgroud)
在这里我们已经接管了,__getattr__()以便在Python尝试从我们的向量中找到属性的许多场景中,它改为计算数学点积.
>>> v = Vector([1, 2])
>>> v.Vector([3, 4])
11
>>> v.v
5
Run Code Online (Sandbox Code Playgroud)
如果这种行为的范围受限于感兴趣的领域,那么这种设计模式是否有任何问题?
Ara*_*Fey 11
这是个坏主意.
为什么?因为你所谓的"点运算符"并不是真正的运算符.那是因为右侧的"操作数"被解释为字符串,而不是表达式.这对你来说似乎微不足道,但它有很多问题后果:
Python程序员习惯于foo.bar"获取对象的bar属性foo".将点转换为点积运算符会打破这种期望,并会使阅读代码的人感到困惑.这是不直观的.
这是不明确的,因为您无法知道用户是否正在尝试计算点积或访问属性.考虑:
>>> data = Vector([1, 2])
>>> v.data # dot product or accessing the data attribute?
Run Code Online (Sandbox Code Playgroud)
请记住,方法也是属性:
>>> dot = Vector([1, 2])
>>> v.dot # dot product or accessing the dot method?
Run Code Online (Sandbox Code Playgroud)因为右手操作数被解释为一个字符串,所以你必须跳过一大堆箍,把这个字符串变成有用的东西 - 正如你试图做的那样globals()[x],它在全局范围内查找变量.问题是 - 在某些情况下 - 完全不可能只通过名称来访问变量.无论你做什么,你将永远无法访问不再存在的变量,因为它已被垃圾收集:
def func():
v2 = Vector([1, 2])
def closure_func():
return v.v2 # this will never work because v2 is already dead!
return closure_func
closure_func = func()
result = closure_func()
Run Code Online (Sandbox Code Playgroud)因为右侧操作数是一个字符串,所以不能在右侧使用任意表达式.你只限于变量; 尝试在右侧使用其他任何东西都会引发某种异常.更糟糕的是,它甚至不会TypeError像其他运营商那样抛出适当的:
>>> [] + 1
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: can only concatenate list (not "int") to list
>>> v.1
File "<stdin>", line 1
v.1
^
SyntaxError: invalid syntax
Run Code Online (Sandbox Code Playgroud)与实数运算符不同,"点运算符"只能在左侧操作数中实现.所有其他运算符可以在两个相应的dunder方法中的任何一个中实现,例如__add__,__radd__对于+运算符.例:
>>> class Incrementer:
... def __radd__(self, other):
... return other + 1
...
>>> 2 + Incrementer()
3
Run Code Online (Sandbox Code Playgroud)
您的点积不能实现这一点:
>>> my_v = MyCustomVector()
>>> v.my_v
AttributeError: 'MyCustomVector' object has no attribute 'data'
Run Code Online (Sandbox Code Playgroud)结论:dot在您的Vector课程中实施方法是可行的方法.由于点不是真正的运算符,因此尝试将其转换为一个运算符必然会适得其反.
| 归档时间: |
|
| 查看次数: |
299 次 |
| 最近记录: |