简体   繁体   中英

How does Python interface work (in Twisted)?

I am following this explanation , and I don't quite get how Python interpreter arrives at the following. In the first example, is Python seeing @implementer(IAmericanSocket) is not implemented by UKSocket , then it decides to make it a AdaptToAmericanSocket because that is the only implementation of IAmericanSocket with one argument? What if there is another class instance implementing IAmericanSocket with one argument? In the second example, why is IAmericanSocket not overriding AmericanSocket 's voltage method?

>>> IAmericanSocket(uk)
<__main__.AdaptToAmericanSocket instance at 0x1a5120>
>>> IAmericanSocket(am)
<__main__.AmericanSocket instance at 0x36bff0>

with the code below:

from zope.interface import Interface, implementer
from twisted.python import components

class IAmericanSocket(Interface):
    def voltage():
      """
      Return the voltage produced by this socket object, as an integer.
      """

@implementer(IAmericanSocket)
class AmericanSocket:
    def voltage(self):
        return 120

class UKSocket:
    def voltage(self):
        return 240

@implementer(IAmericanSocket)
class AdaptToAmericanSocket:
    def __init__(self, original):
        self.original = original

    def voltage(self):
        return self.original.voltage() / 2

components.registerAdapter(
    AdaptToAmericanSocket,
    UKSocket,
    IAmericanSocket)

You can see the full documentation for zope.interface here: http://docs.zope.org/zope.interface/ - it may provide a more thorough introduction than Twisted's quick tutorial.

To answer your specific question, the registerAdapter call at the end there changes the behavior of calling IAmericanSocket .

When you call an Interface , it first checks to see if its argument provides itself. Since the class AmericanSocket implements IAmericanSocket , instances of AmericanSocket provide IAmericanSocket . This means that when you call IAmercianSocket with an argument of an AmericanSocket instance, you just get the instance back.

However, when the argument does not provide the interface already, the interface then searches for adapters which can convert something that the argument does provide to the target interface. ("Searches for adapters" is a huge oversimplification, but Twisted's registerAdapter exists specifically to allow for this type of simplification.)

So when IAmericanSocket is called with an instance of a UKSocket , it finds a registered adapter from instances of UKSocket . The adapter itself is a 1-argument callable that takes an argument of the type being adapted "from" ( UKSocket ) and returns a value of the type being adapted "to" (provider of IAmericanSocket ). AdaptToAmericanSocket is a class, but classes are themselves callable, and since its constructor takes a UKSocket , it fits the contract of thing-that-takes-1-argument-of-type- UKSocket -and-returns-an- IAmericanSocket .

The existence of another class would not make a difference, unless it were registered as an adapter. If you register two adapters which might both be suitable their interactions are complicated, but since they both do the job, in theory you shouldn't care which one gets used.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM