从列表中,动态创建具有名称意识的方法
From a list, dynamically create methods with name-awareness
我正在尝试编写一个简单的控制台颜色实用程序,它采用 class 充满 ANSI 代码并在我的控制台实用程序上生成一些辅助方法,因此我没有执行 console.add('text', 'blue')
,而是可以做到 console.blue('text')
.
我知道我可以静态定义所有这些(例如 def blue(self, s):
),但是如果我想添加 100 个左右的助手(不是我愿意,但是 如果...)
这是简单的 ANSI 映射:
class _AnsiColors:
def __init__(self):
self.green = 35
self.red = 1
self.blue = 32
self.yellow = 214
self.amber = 208
self.olive = 106
self.orange = 166
self.purple = 18
self.pink = 197
self.gray = 243
self.dark_gray = 238
self.light_gray = 248
self.black = 0
self.white = 255
self.debug = 24
ansi = _AnsiColors()
和控制台实用程序(将方法代理到 pyfancy
并使用 colors
):
import copy
from colors import color
from pyfancy import *
from ansi import ansi
class console(object):
def __init__(self, s):
self._s = pyfancy(s)
def add(self, s, c='white'):
if hasattr(ansi, self.add.__name__):
c = self.add.__name__
self._s.add(color(s, fg=getattr(ansi, c)))
return self
def bold(self, s):
self._s.bold(s)
return self
def raw(self, s):
self._s.raw(s)
return self
def dim(self, s):
self._s.dim(s)
return self
def print(self):
self._s.output()
# Inject ansi color convenience methods
for c in vars(ansi):
setattr(console, c, copy.deepcopy(console.add))
getattr(console, c).__name__ = c
那我就可以这样用了:
console('raw').bold(' bold').raw(' raw').blue(' blue').red(' red').print()
你可以看到辅助方法 blue
和 red
至少执行了,所以我对 add()
的复制有效,但是这里发生了什么(尽管我认为我可以解决它与 copy.deepcopy
), 是当我尝试设置每个方法副本的 __name__
属性 时,它设置了对 add
的引用,我最终得到了所有彩色输出的颜色相同 (ansi.debug
)。
有没有办法在不静态定义每个助手的情况下完成我想做的事情?
没有 colors/pyfancy 的 MCVE:
import copy
from ansi import ansi
class console(object):
def __init__(self, s):
self._s = s
def add(self, s, c='white'):
if hasattr(ansi, self.add.__name__):
c = self.add.__name__
self._s += '%s(%s)' % (s, c)
return self
def print(self):
print(self._s)
# Inject ansi color convenience methods
for c in vars(ansi):
setattr(console, c, copy.deepcopy(console.add))
getattr(console, c).__name__ = c
console('white').blue(' blue').red(' red').print()
# white blue(debug) red(debug)
我会用闭包来解决:
class console(object):
def __init__(self, s):
self._s = s
for color in vars(ansi):
self._colorizer(color)
def _colorizer(self, c):
def add(s):
self._s += '%s(%s)' % (s, c)
return self
self.__setattr__(c, add)
def print(self):
print(self._s)
console('white').blue(' blue').red(' red').print()
# white blue(blue) red(red)
我正在尝试编写一个简单的控制台颜色实用程序,它采用 class 充满 ANSI 代码并在我的控制台实用程序上生成一些辅助方法,因此我没有执行 console.add('text', 'blue')
,而是可以做到 console.blue('text')
.
我知道我可以静态定义所有这些(例如 def blue(self, s):
),但是如果我想添加 100 个左右的助手(不是我愿意,但是 如果...)
这是简单的 ANSI 映射:
class _AnsiColors:
def __init__(self):
self.green = 35
self.red = 1
self.blue = 32
self.yellow = 214
self.amber = 208
self.olive = 106
self.orange = 166
self.purple = 18
self.pink = 197
self.gray = 243
self.dark_gray = 238
self.light_gray = 248
self.black = 0
self.white = 255
self.debug = 24
ansi = _AnsiColors()
和控制台实用程序(将方法代理到 pyfancy
并使用 colors
):
import copy
from colors import color
from pyfancy import *
from ansi import ansi
class console(object):
def __init__(self, s):
self._s = pyfancy(s)
def add(self, s, c='white'):
if hasattr(ansi, self.add.__name__):
c = self.add.__name__
self._s.add(color(s, fg=getattr(ansi, c)))
return self
def bold(self, s):
self._s.bold(s)
return self
def raw(self, s):
self._s.raw(s)
return self
def dim(self, s):
self._s.dim(s)
return self
def print(self):
self._s.output()
# Inject ansi color convenience methods
for c in vars(ansi):
setattr(console, c, copy.deepcopy(console.add))
getattr(console, c).__name__ = c
那我就可以这样用了:
console('raw').bold(' bold').raw(' raw').blue(' blue').red(' red').print()
你可以看到辅助方法 blue
和 red
至少执行了,所以我对 add()
的复制有效,但是这里发生了什么(尽管我认为我可以解决它与 copy.deepcopy
), 是当我尝试设置每个方法副本的 __name__
属性 时,它设置了对 add
的引用,我最终得到了所有彩色输出的颜色相同 (ansi.debug
)。
有没有办法在不静态定义每个助手的情况下完成我想做的事情?
没有 colors/pyfancy 的 MCVE:
import copy
from ansi import ansi
class console(object):
def __init__(self, s):
self._s = s
def add(self, s, c='white'):
if hasattr(ansi, self.add.__name__):
c = self.add.__name__
self._s += '%s(%s)' % (s, c)
return self
def print(self):
print(self._s)
# Inject ansi color convenience methods
for c in vars(ansi):
setattr(console, c, copy.deepcopy(console.add))
getattr(console, c).__name__ = c
console('white').blue(' blue').red(' red').print()
# white blue(debug) red(debug)
我会用闭包来解决:
class console(object):
def __init__(self, s):
self._s = s
for color in vars(ansi):
self._colorizer(color)
def _colorizer(self, c):
def add(s):
self._s += '%s(%s)' % (s, c)
return self
self.__setattr__(c, add)
def print(self):
print(self._s)
console('white').blue(' blue').red(' red').print()
# white blue(blue) red(red)