通常,我发现最好的方法是重写
__ilshift__
作为setter和
__rlshift__
作为getter,并由property装饰器复制。
它几乎是最后一个被解决的运算符(| & ^),逻辑运算符更低。
很少使用(
__lrshift__
更少,但可以考虑)。
在使用PyPi assign包时,只能控制前向赋值,因此运算符的实际 "强度" 较低。
PyPi assign包示例:
class Test:
def __init__(self, val, name):
self._val = val
self._name = name
self.named = False
def __assign__(self, other):
if hasattr(other, 'val'):
other = other.val
self.set(other)
return self
def __rassign__(self, other):
return self.get()
def set(self, val):
self._val = val
def get(self):
if self.named:
return self._name
return self._val
@property
def val(self):
return self._val
x = Test(1, 'x')
y = Test(2, 'y')
print('x.val =', x.val)
print('y.val =', y.val)
x = y
print('x.val =', x.val)
z: int = None
z = x
print('z =', z)
x = 3
y = x
print('y.val =', y.val)
y.val = 4
输出:
x.val = 1
y.val = 2
x.val = 2
z = <__main__.Test object at 0x0000029209DFD978>
Traceback (most recent call last):
File "E:\packages\pyksp\pyksp\compiler2\simple_test2.py", line 44, in <module>
print('y.val =', y.val)
AttributeError: 'int' object has no attribute 'val'
同样适用于Shift:
class Test:
def __init__(self, val, name):
self._val = val
self._name = name
self.named = False
def __ilshift__(self, other):
if hasattr(other, 'val'):
other = other.val
self.set(other)
return self
def __rlshift__(self, other):
return self.get()
def set(self, val):
self._val = val
def get(self):
if self.named:
return self._name
return self._val
@property
def val(self):
return self._val
x = Test(1, 'x')
y = Test(2, 'y')
print('x.val =', x.val)
print('y.val =', y.val)
x <<= y
print('x.val =', x.val)
z: int = None
z <<= x
print('z =', z)
x <<= 3
y <<= x
print('y.val =', y.val)
y.val = 4
输出:
x.val = 1
y.val = 2
x.val = 2
z = 2
y.val = 3
Traceback (most recent call last):
File "E:\packages\pyksp\pyksp\compiler2\simple_test.py", line 45, in <module>
y.val = 4
AttributeError: can't set attribute
所以,在获取属性值时使用
<<=
运算符是更加视觉清晰的解决方案,不会让用户犯一些反射性错误,例如:
var1.val = 1
var2.val = 2
var1.val = var2
var1.val = var2.val
somevar = var1 + var2
var1 += var2
var1 = var2
exec in d
来执行这段代码,其中 d 是某个字典。如果代码在模块级别上,每个赋值都应该被发送回字典。你可以在执行后恢复你的值/检查值是否改变,或者拦截字典赋值,即用另一个对象替换变量的字典。 - Ant6nScreenUpdating = False
是不可能的。 - Winand__all__
属性 来防止私有数据被导出,这是 Python 标准库常用的方法。 - Benx=1
和x=2
会报错。 - Poojan