11

元のメソッドと残りの引数を取るラッパー メソッドにリダイレクトする約 20 のメソッドがあります。

class my_socket(parent):

    def _in(self, method, *args, **kwargs):
        # do funky stuff

    def recv(self, *args, **kwargs):
        return self._in(super().recv, *args, **kwargs)

    def recv_into(self, *args, **kwargs):
        return self._in(super().recv_into, *args, **kwargs)

    # and so on...

これらのメソッドをプログラムでさらに追加するにはどうすればよいですか? これは、すべてが間違っているように見える前に私が得た限りです。

for method in 'recv', 'recvfrom', 'recvfrom_into', 'recv_into', ...:
    setattr(my_socket, method, ???)

クラス定義内で割り当てるか、より自然に感じる何か他のものでこれを行うことはできますか?

class my_socket(parent):

    def makes_recv_methods(name):
        # wraps call to name

    def recv_meh = makes_recv_methods('recv_meh')

__get__からの魔法の機能よりも、可能な場合は友人を使用したいと思いtypesます。

4

4 に答える 4

9

クラスが定義された後、いくつかのコードを実行してリストからメソッドを生成することでそれを行います-これをデコレータに入れることができます。

import functools

def wrap_method(cls, name):
    # This unbound method will be pulled from the superclass.
    wrapped = getattr(cls, name)
    @functools.wraps(wrapped)
    def wrapper(self, *args, **kwargs):
        return self._in(wrapped.__get__(self, cls), *args, **kwargs)
    return wrapper

def wrap_methods(cls):
    for name in cls.WRAP_ATTRS:
        setattr(cls, name, wrap_method(cls, name))
    return cls

@wrap_methods
class my_socket(parent_class):
    WRAP_ATTRS = ['recv', 'recvfrom'] # ... + more method names

    def _in(self, method, *args, **kwargs):
        # do funky stuff
于 2011-11-29T11:06:44.493 に答える
0

wilberforce の提案は機能しますが、OOP のみを使用するより簡単な方法があります。

def wrap_method(wrapped):
    @functools.wraps(wrapped)
    def wrapper(self, *args, **kwargs):
        return self._in(wrapped.__get__(self, cls), *args, **kwargs)
    return wrapper

class Parent:

    def _in(self, method, *args, **kwargs):
        return method(*args, **kwargs)


    @wrap_method
    def recv(self, *args, **kwargs):
        return # whatever

    @wrap_method
    def recv_into(self, *args, **kwargs):
        return # whatever

class MySocket(Parent):

    def _in(self, method, *args, **kwargs):
        # do funky stuff
于 2011-11-29T14:59:55.490 に答える
-2

cogを使用できます。

class MySocket(Parent):
"""[[[cog
import cog
l = ['in','out']
for item in l:
    cog.outl("def _{0}(self, method, *args, **kwargs):".format(item))

]]]"""
#[[[end]]]

これには、簡単に更新できるという追加の利点があり、終了コメント以外のコードに触れず、必要に応じて生成されたコードをいじることができます。

生成されていないコードと混合して、別のプロジェクトでボイラープレートを生成するために cog を使用することに成功しました。命令の入力ファイルを辞書に読み込むことから始めました。次に、ボイラープレートの各セクションに対して、辞書のその部分を使用して、何を書くべきかを判断しました。

定型文の 20 か所ではなく、1 か所で命令ファイルを編集します。

于 2011-11-29T15:15:16.873 に答える