代码之家  ›  专栏  ›  技术社区  ›  brandonscript

从列表中,动态创建具有名称感知的方法

  •  4
  • brandonscript  · 技术社区  · 8 年前

    我正在尝试编写一个简单的控制台颜色实用程序,它接受一个满是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 ).

    有没有一种方法可以在不静态定义每个助手的情况下完成我要做的事情?


    MCVE无颜色/pyfancy:

    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)
    
    1 回复  |  直到 8 年前
        1
  •  1
  •   membranepotential    8 年前

    我会用闭包来解决这个问题:

    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)