1. <legend id='Qhpx3'><style id='Qhpx3'><dir id='Qhpx3'><q id='Qhpx3'></q></dir></style></legend>

    <i id='Qhpx3'><tr id='Qhpx3'><dt id='Qhpx3'><q id='Qhpx3'><span id='Qhpx3'><b id='Qhpx3'><form id='Qhpx3'><ins id='Qhpx3'></ins><ul id='Qhpx3'></ul><sub id='Qhpx3'></sub></form><legend id='Qhpx3'></legend><bdo id='Qhpx3'><pre id='Qhpx3'><center id='Qhpx3'></center></pre></bdo></b><th id='Qhpx3'></th></span></q></dt></tr></i><div id='Qhpx3'><tfoot id='Qhpx3'></tfoot><dl id='Qhpx3'><fieldset id='Qhpx3'></fieldset></dl></div>

    <small id='Qhpx3'></small><noframes id='Qhpx3'>

    • <bdo id='Qhpx3'></bdo><ul id='Qhpx3'></ul>

      <tfoot id='Qhpx3'></tfoot>

      在 Python 中模拟成员资格测试:将 __contains__ 正确委派给包含对象

      Emulating membership-test in Python: delegating __contains__ to contained-object correctly(在 Python 中模拟成员资格测试:将 __contains__ 正确委派给包含对象)

      • <i id='bStx0'><tr id='bStx0'><dt id='bStx0'><q id='bStx0'><span id='bStx0'><b id='bStx0'><form id='bStx0'><ins id='bStx0'></ins><ul id='bStx0'></ul><sub id='bStx0'></sub></form><legend id='bStx0'></legend><bdo id='bStx0'><pre id='bStx0'><center id='bStx0'></center></pre></bdo></b><th id='bStx0'></th></span></q></dt></tr></i><div id='bStx0'><tfoot id='bStx0'></tfoot><dl id='bStx0'><fieldset id='bStx0'></fieldset></dl></div>

          <small id='bStx0'></small><noframes id='bStx0'>

            <tfoot id='bStx0'></tfoot>
            <legend id='bStx0'><style id='bStx0'><dir id='bStx0'><q id='bStx0'></q></dir></style></legend>
              <bdo id='bStx0'></bdo><ul id='bStx0'></ul>

                  <tbody id='bStx0'></tbody>
                本文介绍了在 Python 中模拟成员资格测试:将 __contains__ 正确委派给包含对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着跟版网的小编来一起学习吧!

                问题描述

                我已经习惯了 Python 允许一些巧妙的技巧将功能委托给其他对象.一个例子是委托给包含的对象.

                I am used to that Python allows some neat tricks to delegate functionality to other objects. One example is delegation to contained objects.

                但是当我想委托 __contains __ 时,我没有运气:

                But it seams, that I don't have luck, when I want to delegate __contains __:

                class A(object):
                    def __init__(self):
                       self.mydict = {}
                       self.__contains__ = self.mydict.__contains__
                
                a = A()
                1 in a
                

                我明白了:

                Traceback (most recent call last):
                File "<stdin>", line 1, in <module>
                TypeError: argument of type 'A' is not iterable
                

                我做错了什么?当我调用 a.__contains __(1) 时,一切都很顺利.我什至尝试在 A 中定义一个 __iter __ 方法,以使 A 看起来更像一个可迭代的,但它没有帮助.我在这里错过了什么?

                What I am making wrong? When I call a.__contains __(1), everything goes smooth. I even tried to define an __iter __ method in A to make A more look like an iterable, but it did not help. What I am missing out here?

                推荐答案

                __contains__ 等特殊方法仅在类上定义时才具有特殊性,而不是在实例上(Python 2 中的遗留类除外,你应该使用它).

                Special methods such as __contains__ are only special when defined on the class, not on the instance (except in legacy classes in Python 2, which you should not use anyway).

                所以,在课堂上做你的委派:

                So, do your delegation at class level:

                class A(object):
                    def __init__(self):
                       self.mydict = {}
                
                    def __contains__(self, other):
                       return self.mydict.__contains__(other)
                

                我实际上更喜欢将后者拼写为 return other in self.mydict,但这是一个小风格问题.

                I'd actually prefer to spell the latter as return other in self.mydict, but that's a minor style issue.

                编辑:如果特殊方法的完全动态的每个实例重定向"(如提供的旧式类)是必不可少的,那么用新式类实现它并不难:你只需要将每个具有这种特殊需求的实例包装在自己的特殊类中即可.例如:

                Edit: if and when "totally dynamic per-instance redirecting of special methods" (like old-style classes offered) is indispensable, it's not hard to implement it with new-style classes: you just need each instance that has such peculiar need to be wrapped in its own special class. For example:

                class BlackMagic(object):
                    def __init__(self):
                        self.mydict = {}
                        self.__class__ = type(self.__class__.__name__, (self.__class__,), {})
                        self.__class__.__contains__ = self.mydict.__contains__
                

                本质上,经过一点点黑魔法将 self.__class__ 重新分配给一个新的类对象(其行为与前一个类似,但有一个空的 dict 并且除了这个之外没有其他实例 self),在你将分配给 self.__magicname__ 的旧式类中的任何位置,改为分配给 self.__class__.__magicname__(并确保它是内置或 staticmethod,不是普通的 Python 函数,当然,除非在某些不同的情况下您确实希望它在实例上调用时接收 self).

                Essentially, after the little bit of black magic reassigning self.__class__ to a new class object (which behaves just like the previous one but has an empty dict and no other instances except this one self), anywhere in an old-style class you would assign to self.__magicname__, assign to self.__class__.__magicname__ instead (and make sure it's a built-in or staticmethod, not a normal Python function, unless of course in some different case you do want it to receive the self when called on the instance).

                顺便说一下,这个 BlackMagic 类的实例上的 in 操作符比之前提出的任何操作都解决方案——或者至少我用我通常信任的 -mtimeit 进行测量(直接进入 built-in method,而不是遵循涉及继承和描述符,减少了一些开销).

                Incidentally, the in operator on an instance of this BlackMagic class is faster, as it happens, than with any of the previously proposed solutions -- or at least so I'm measuring with my usual trusty -mtimeit (going directly to the built-in method, instead of following normal lookup routes involving inheritance and descriptors, shaves a bit of the overhead).

                一个自动实现 self.__class__-per-instance 想法的元类并不难编写(它可以在生成的类的 __new__ 方法中完成繁琐的工作,如果通过 __setattr__ 或许多 many 属性在实例上分配,也可以将所有魔术名称设置为实际分配给类).但这只有在对这个特性的需求真的很普遍的情况下才是合理的(例如,将一个巨大的古老的 Python 1.5.2 项目移植到现代 Python,包括 Python 3).

                A metaclass to automate the self.__class__-per-instance idea would not be hard to write (it could do the dirty work in the generated class's __new__ method, and maybe also set all magic names to actually assign on the class if assigned on the instance, either via __setattr__ or many, many properties). But that would be justified only if the need for this feature was really widespread (e.g. porting a huge ancient Python 1.5.2 project that liberally use "per-instance special methods" to modern Python, including Python 3).

                推荐聪明"还是黑魔法"解决方案?不,我不这样做:几乎总是以简单、直接的方式做事更好.但是几乎"在这里是一个重要的词,很高兴手头有这样高级的钩子",用于可能实际需要使用它们的罕见但并非不存在的情况.

                Do I recommend "clever" or "black magic" solutions? No, I don't: almost invariably it's better to do things in simple, straightforward ways. But "almost" is an important word here, and it's nice to have at hand such advanced "hooks" for the rare, but not non-existent, situations where their use may actually be warranted.

                这篇关于在 Python 中模拟成员资格测试:将 __contains__ 正确委派给包含对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!

                本站部分内容来源互联网,如果有图片或者内容侵犯了您的权益,请联系我们,我们会在确认后第一时间进行删除!

                相关文档推荐

                What happens when you compare 2 pandas Series(当你比较 2 个 pandas 系列时会发生什么)
                Quickly find differences between two large text files(快速查找两个大文本文件之间的差异)
                Python - Compare 2 files and output differences(Python - 比较 2 个文件和输出差异)
                Why do comparisions between very large float values fail in python?(为什么在 python 中非常大的浮点值之间的比较会失败?)
                Dictionary merge by updating but not overwriting if value exists(字典通过更新合并,但如果值存在则不覆盖)
                Find entries of one text file in another file in python(在python中的另一个文件中查找一个文本文件的条目)
                  <bdo id='xXpUk'></bdo><ul id='xXpUk'></ul>

                      <tbody id='xXpUk'></tbody>

                    <i id='xXpUk'><tr id='xXpUk'><dt id='xXpUk'><q id='xXpUk'><span id='xXpUk'><b id='xXpUk'><form id='xXpUk'><ins id='xXpUk'></ins><ul id='xXpUk'></ul><sub id='xXpUk'></sub></form><legend id='xXpUk'></legend><bdo id='xXpUk'><pre id='xXpUk'><center id='xXpUk'></center></pre></bdo></b><th id='xXpUk'></th></span></q></dt></tr></i><div id='xXpUk'><tfoot id='xXpUk'></tfoot><dl id='xXpUk'><fieldset id='xXpUk'></fieldset></dl></div>
                    <tfoot id='xXpUk'></tfoot>

                        <small id='xXpUk'></small><noframes id='xXpUk'>

                      1. <legend id='xXpUk'><style id='xXpUk'><dir id='xXpUk'><q id='xXpUk'></q></dir></style></legend>