有没有办法:
以一种不仅会扼杀Python程序员期望的方式覆盖赋值?
port = IntContainer(80)
port = 8080 # set the IntContainer contents to 8080
# instead of changing what the port name references
# from the IntContainer(80) to int(8080)
覆盖丰富的比较器,使得二元比较运算符的参数顺序无关紧要?
port = IntContainer(80)
port < 80 # False
80 > port # TypeError
@BrenBarn:
什么版本的Python?我正在使用3.4.3:
class Foo(object):
def __lt__(self, other):
return self.value < other
def __init__(self, other):
self.value = other
foo = Foo(1)
foo < 1 # False
1 > foo # raise TypeError()
logging
消息都需要设置Handler
级别,那显然很糟糕。我已经为list
和dict
容器配置类型编写了此代码。我使用blinker
lib进行信令。这些物品很聪明;信号从叶子传播到任何包含它们的对象(不是树木或森林,因为它们是可重新组合的)。每个广播给他们的订户,包括其他容器配置,以及实际的用户订户。例如:
def receive_a(signal):
print('Object 'a' received {} event at path {}; prev: {!r}, curr: {!r}'.format(
signal.type, signal.path, signal.prev, signal.curr
))
config_dict_a = ConfigDict()
config_dict_a.connect(receive_a)
def receive_b(signal):
print('Object 'b' received {} event at path {}; prev: {!r}, curr: {!r}'.format(
signal.type.name, signal.path, signal.prev, signal.curr
))
config_dict_b = ConfigDict()
config_dict_b.connect(receive_b)
config_dict_a['b'] = config_dict_b
# Object 'a' received INSERT event at path ('b',); prev: None, curr: {}
# Object 'a' received UPDATE event at path (); prev: {}, curr: {'b': {}}
config_dict_b['foo'] = 42
# Object 'b' received INSERT event at path ('foo',); prev: None, curr: 42
# Object 'b' received UPDATE event at path (); prev: {}, curr: {'foo': 42}
# Object 'a' received INSERT event at path ('b', 'foo'); prev: None, curr: 42
# Object 'a' received UPDATE event at path ('b',); prev: {}, curr: {'foo': 42}
# Object 'a' received UPDATE event at path (); prev: {'b': {}}, curr: {'b': {'foo': 42}}
del config_a['b']['foo']
# Object 'b' received DELETE event at path ('foo',); prev: 42, curr: None
# Object 'b' received UPDATE event at path (); prev: {'foo': 42}, curr: {}
# Object 'a' received DELETE event at path ('b', 'foo',); prev: 42, curr: None
# Object 'a' received UPDATE event at path ('b',); prev: {'foo': 42}, curr: {}
# Object 'a' received UPDATE event at path (); prev: {'b': {'foo': 42}}, curr: {'b': {}}
只需订阅您想要的那个,然后聆听您想要的确切路径。当存在子服务或工作者时,这对于Python进程级别的配置尤其有用。该过程可以分割其配置,重新组合为特定于每个组成部分的新根配置,并将其交给部件供他们订阅。
从较低级别邮件撰写更高级别邮件的安全性只需要本地锁定,而不是全局锁定。
list
和dict
作为容器类型,本质上是一种引用类型 - 这就是它们可变的原因。我的Config<Container>
对象可以从外部读取,就像__getitem__
对任何东西一样。他们扩展collections.abc
个东西,所以他们工作。你也可以用同样的方式写信给他们,没有任何时髦的self.set(value)
符号。
但深不可变的标量(Hashable
)不是。其中包括int
,str
,甚至NoneType
。这些不能直接替代:
我无法覆盖任务,理由很充分(这很疯狂)。
int_a = ConfigInt()
int_a = 2
# swap out what the name 'int_a' refers to, or modify the internal contents?
# obviously crazy
无论如何我需要支持set(value)
,所以1.
无论如何。
如果不对内置类型进行子类化,我无法进行比较。
此外,没有虚拟子类来扩展左右交换问题的相等或比较:
port = ConfigInt()
port > 40 # True
40 < port # TypeError()
这些都不是不可克服的,但好的库对你很好。我真的想解决这个问题。特别是对于标量完全是工人需要的情况 - 比如Flask greenlet或其他东西 - 标量是顶级对象,我们不应该将它包装在dict
中。
答案 0 :(得分:2)
以一种不会扼杀Python程序员的方式覆盖作业&#39;期望?
不,你根本不能将普通作业改为裸名。正如您在问题中稍后提到的那样,您需要使用set
方法等。
覆盖丰富的比较器,使得二元比较运算符的参数顺序无关紧要?
已经有效:
class Foo:
def __init__(self, val):
self.val = val
def __lt__(self, other):
if isinstance(other, Foo):
return self.val < other.val
else:
return self.val < other
>>> Foo(3) < 10
True
>>> 10 > Foo(3)
True
当然,在与其他类型进行比较时,您可能需要考虑一下您希望行为的内容,以及其他类型&#34;。在这里,我只是比较&#34;存储的值&#34; Foo
对象的直接与另一个值的关系,如果其他值也不是Foo。