Я пытаюсь написать оболочку для внешнего модуля в python. Модуль предоставляет метод сопряжения глагола, который ожидает 2 аргумента. Я хотел бы объединить его в несколько методов, и мне было интересно, есть ли способ сделать это программно.
то есть. вместо:
class X:
def a(self,arg):
return module.do(arg,'a')
def b(self,arg):
return module.do(arg,'b')
...
def z(self,arg):
return module.do(arg,'z')
Я пытался:
class X:
def a(self,arg):
return module.do(arg,__name__)
return module.do(arg,__name__)
def __init__(self):
setattr(self,'b',self.a)
...
setattr(self,'z',self.a)
x = X()
x.a(y)
x.b(y)
x.z(y)
Проблема заключается в том, что имя возвращает метод верхнего уровня, а не текущий. Я попробовал оба:
from inspect import stack
stack()[0][3]
import sys
sys._getframe().f_code.co_name
Но когда я называю b() или z(), я получаю 'a'. Я делаю что-то неправильно? Есть ли другой способ достижения аналогичного результата?
Вы просто устанавливаете все атрибуты b
to z
своего класса, чтобы указать на метод a
. Это означает, что всякий раз, когда кто-то обращается к instance.b
, он возвращает метод a
(поэтому co_name
всегда a
).
Вы можете выполнить то, что хотите:
import string
class X(object):
def __getattr__(self, name):
if name in string.lowercase and len(name) == 1:
def call_into_module(arg):
return module.do(arg, name)
return call_into_module
return super(X, self).__getattr__(name)
name in string.lowercase
предназначено для проверки, является ли name
одной строчной буквой? Это не так.
Вы можете сделать что-то вроде
class X:
pass
for name in "abcdefghij":
setattr(X, name, lambda self, arg, _name=name: module.do(arg, _name))
Достаточно добавить методы в класс один раз - это не обязательно делать для каждого экземпляра в __init__()
.
Возможно, лучшей альтернативой является перезапись __getattr__()
:
class X:
def __getattr__(self, name):
def foo(arg):
return module.do(arg, name)
return foo