Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/366.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/python-2.7/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在python中向类添加名称为字符串的函数?_Python_Python 2.7_Class - Fatal编程技术网

如何在python中向类添加名称为字符串的函数?

如何在python中向类添加名称为字符串的函数?,python,python-2.7,class,Python,Python 2.7,Class,我有几个类,它们的方法都遵循相同的结构。为了这个例子,让我们假设它是 class Foo: def say_hello(self,a,b,c,d) : print("hello" + a + b + c + d) def say_moo(self,a,b,c,d) : print("moo" + a + b + c + d) def say_foo(self,a,b,c,d) : print("foo" + a + b + c + d) # more of the

我有几个类,它们的方法都遵循相同的结构。为了这个例子,让我们假设它是

class Foo:
    def say_hello(self,a,b,c,d) : print("hello" + a + b + c + d)
    def say_moo(self,a,b,c,d) : print("moo" + a + b + c + d)
    def say_foo(self,a,b,c,d) : print("foo" + a + b + c + d)
    # more of the same pattern...

class Bar:
    def say_hello(self,a,b,c,d) : print("hello" + a + b + c + d)
    def say_bar(self,a,b,c,d) : print("bar" + a + b + c + d)
    def say_boo(self,a,b,c,d) : print("boo" + a + b + c + d)

#more classes of the same pattern...
拥有这些方法是一项要求,因此简单地使用
def sayx(self,x,a,b,c,d):print(x+a+b+c+d)
并不是一个解决方案

我想避免重复我自己那么多,我正在寻找一种方法来写一些关于

class Foo :
   def SOME_MAGIC("hello")
   def SOME_MAGIC("moo")
   def SOME_MAGIC("foo")
这将产生与上述
Foo
等效的结果。搜索主题时,我总是接触到一些元类,但它们总是伴随着便条:“如果你想知道你是否需要它们,你不需要。”。因此,我显然不需要它们。我需要什么

你在找什么


或者,您可以使用:

测试:

好处是您只需定义字符串一次。缺点是可读性不太明显

如果类之间的
say()
是通用的,您甚至可以这样做:

from functools import partialmethod

def add_say(cls, *cmds:str):
    def say(self, x, a, b, c, d):
        print(x, a, b, c, d)
        # ... do something with self if you need ...

    for cmd in cmds:
        setattr(cls, f'say_{cmd}', partialmethod(say, cmd))

class Foo:
    def __init__(self):
        add_say(Foo, 'hello', 'moo', 'boo')

class Bar:
    def __init__(self):
        add_say(Bar, 'hello', 'bar', 'baz')
测试:

代码需要进行调整,以实现Python 3的兼容性


我故意避免使用functools助手。我不鼓励上面的代码,因为它会使堆栈跟踪更加详细,破坏静态分析工具,使动态内省更加困难,并且通常比不太动态的方法更容易混淆。

在这里,您可以利用继承。使类
Foo
Bar
从另一个单独的类继承
一些魔法
,如
BarStool
@hampusralson大多数方法在
Foo
Bar
(以及其他)中不同,只有少数例外。我知道我可以将
say_hello
移动到一个基类,但我知道如何在这里使用继承,我希望我只能写一次
hello
,但这已经接近了Enough标记了他们的问题python2.7,我认为格式字符串或类型注释不兼容。每次创建实例时,执行任一解决方案都会创建并绑定新的分部函数。在第一个解决方案中,这些方法根本不存在于类中。在我看来,这两种解决方案都是不好的。对于后一种解决方案,在创建实例之前,该方法不会存在于dict类中。这可能会导致意外的问题:无异常执行
Foo。say_hello(Foo(),*range(4))
将取决于是否在它之前创建了Foo的实例。很公平,我没有捕获python2.7标记。然而,我认为这里最明显、最清晰的解决方案就是写出所有的
say_which
方法,因为它在整个代码库中更加清晰、可读和可管理。在我看来,强制使用一种不同的
say_which
方法来做相同的事情是一个需要重新考虑的设计决策,但这显然是OP无法控制的。
from functools import partial
class Foo:
    def __init__(self):     
        cmds = ('hello', 'moo', 'boo')  # only define your strings once
        for c in cmds:
            setattr(self, f'say_{c}', partial(self.say, c))

    def say(self, x, a, b, c, d):
        print(x + a + b + c + d)
>>> f = Foo()
>>> f.say_hello(*'abcd')
helloabcd
>>> f.say_boo(*'1234')
boo1234
from functools import partialmethod

def add_say(cls, *cmds:str):
    def say(self, x, a, b, c, d):
        print(x, a, b, c, d)
        # ... do something with self if you need ...

    for cmd in cmds:
        setattr(cls, f'say_{cmd}', partialmethod(say, cmd))

class Foo:
    def __init__(self):
        add_say(Foo, 'hello', 'moo', 'boo')

class Bar:
    def __init__(self):
        add_say(Bar, 'hello', 'bar', 'baz')
>>> f = Foo()
>>> f.say_boo(*'abcd')
boo a b c d
>>> b = Bar()
>>> b.say_baz(*'dude')
baz d u d e
from __future__ import print_function

class SayMetaClass( type ):
    def __new__( mcls, name, bases, dict_ ):
        say_template = lambda value: lambda self, a, b, c, d: print( value + a + b + c + d )

        if "SAY_WHAT" in dict_:
            for value in dict_[ "SAY_WHAT" ]:
                method_name = "say_{value}".format( value=value )
                if method_name in dict_:
                    raise ValueError( "{method_name} is already defined in the class!".format( method_name=method_name ) )
                dict_[ method_name ] = say_template( value )

            del dict_[ "SAY_WHAT" ]

        return super( SayMetaClass, mcls ).__new__( mcls, name, bases, dict_ )

class Foo( object ):
    __metaclass__ = SayMetaClass

    SAY_WHAT = [ "hello", "moo", "foo" ]

class Bar( object ):
    __metaclass__ = SayMetaClass

    SAY_WHAT = [ "hello", "bar", "boo" ]

class Baz( Foo, Bar ):
    pass

args = "1234"

f = Foo()
f.say_hello( *args )
f.say_moo( *args )
f.say_foo( *args )

b = Baz()
b.say_hello( *args )
b.say_moo( *args )
b.say_bar( *args )